mirror of
https://github.com/docker/compose.git
synced 2025-07-28 16:14:06 +02:00
Merge pull request #748 from docker/aci_resource_req
Aci resource reservation & limits
This commit is contained in:
commit
7fb976732f
@ -54,7 +54,7 @@ func ContainerToComposeProject(r containers.ContainerConfig) (types.Project, err
|
|||||||
Environment: toComposeEnvs(r.Environment),
|
Environment: toComposeEnvs(r.Environment),
|
||||||
Deploy: &types.DeployConfig{
|
Deploy: &types.DeployConfig{
|
||||||
Resources: types.Resources{
|
Resources: types.Resources{
|
||||||
Limits: &types.Resource{
|
Reservations: &types.Resource{
|
||||||
NanoCPUs: fmt.Sprintf("%f", r.CPULimit),
|
NanoCPUs: fmt.Sprintf("%f", r.CPULimit),
|
||||||
MemoryBytes: types.UnitBytes(r.MemLimit.Value()),
|
MemoryBytes: types.UnitBytes(r.MemLimit.Value()),
|
||||||
},
|
},
|
||||||
|
@ -175,10 +175,6 @@ func getDNSSidecar(containers []containerinstance.Container) containerinstance.C
|
|||||||
Image: to.StringPtr(dnsSidecarImage),
|
Image: to.StringPtr(dnsSidecarImage),
|
||||||
Command: &alpineCmd,
|
Command: &alpineCmd,
|
||||||
Resources: &containerinstance.ResourceRequirements{
|
Resources: &containerinstance.ResourceRequirements{
|
||||||
Limits: &containerinstance.ResourceLimits{
|
|
||||||
MemoryInGB: to.Float64Ptr(0.1), // "The memory requirement should be in incrememts of 0.1 GB."
|
|
||||||
CPU: to.Float64Ptr(0.01), // "The CPU requirement should be in incrememts of 0.01."
|
|
||||||
},
|
|
||||||
Requests: &containerinstance.ResourceRequests{
|
Requests: &containerinstance.ResourceRequests{
|
||||||
MemoryInGB: to.Float64Ptr(0.1),
|
MemoryInGB: to.Float64Ptr(0.1),
|
||||||
CPU: to.Float64Ptr(0.01),
|
CPU: to.Float64Ptr(0.01),
|
||||||
@ -357,38 +353,73 @@ func (s serviceConfigAciHelper) getAciContainer(volumesCache map[string]bool) (c
|
|||||||
volumes = &allVolumes
|
volumes = &allVolumes
|
||||||
}
|
}
|
||||||
|
|
||||||
memLimit := 1. // Default 1 Gb
|
resource, err := s.getResourceRequestsLimits()
|
||||||
var cpuLimit float64 = 1
|
|
||||||
if s.Deploy != nil && s.Deploy.Resources.Limits != nil {
|
|
||||||
if s.Deploy.Resources.Limits.MemoryBytes != 0 {
|
|
||||||
memLimit = bytesToGb(s.Deploy.Resources.Limits.MemoryBytes)
|
|
||||||
}
|
|
||||||
if s.Deploy.Resources.Limits.NanoCPUs != "" {
|
|
||||||
cpuLimit, err = strconv.ParseFloat(s.Deploy.Resources.Limits.NanoCPUs, 0)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return containerinstance.Container{}, err
|
return containerinstance.Container{}, err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return containerinstance.Container{
|
return containerinstance.Container{
|
||||||
Name: to.StringPtr(s.Name),
|
Name: to.StringPtr(s.Name),
|
||||||
ContainerProperties: &containerinstance.ContainerProperties{
|
ContainerProperties: &containerinstance.ContainerProperties{
|
||||||
Image: to.StringPtr(s.Image),
|
Image: to.StringPtr(s.Image),
|
||||||
Command: to.StringSlicePtr(s.Command),
|
Command: to.StringSlicePtr(s.Command),
|
||||||
EnvironmentVariables: getEnvVariables(s.Environment),
|
EnvironmentVariables: getEnvVariables(s.Environment),
|
||||||
Resources: &containerinstance.ResourceRequirements{
|
Resources: resource,
|
||||||
|
VolumeMounts: volumes,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s serviceConfigAciHelper) getResourceRequestsLimits() (*containerinstance.ResourceRequirements, error) {
|
||||||
|
memRequest := 1. // Default 1 Gb
|
||||||
|
var cpuRequest float64 = 1
|
||||||
|
var err error
|
||||||
|
hasMemoryRequest := func() bool {
|
||||||
|
return s.Deploy != nil && s.Deploy.Resources.Reservations != nil && s.Deploy.Resources.Reservations.MemoryBytes != 0
|
||||||
|
}
|
||||||
|
hasCPURequest := func() bool {
|
||||||
|
return s.Deploy != nil && s.Deploy.Resources.Reservations != nil && s.Deploy.Resources.Reservations.NanoCPUs != ""
|
||||||
|
}
|
||||||
|
if hasMemoryRequest() {
|
||||||
|
memRequest = bytesToGb(s.Deploy.Resources.Reservations.MemoryBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasCPURequest() {
|
||||||
|
cpuRequest, err = strconv.ParseFloat(s.Deploy.Resources.Reservations.NanoCPUs, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memLimit := memRequest
|
||||||
|
cpuLimit := cpuRequest
|
||||||
|
if s.Deploy != nil && s.Deploy.Resources.Limits != nil {
|
||||||
|
if s.Deploy.Resources.Limits.MemoryBytes != 0 {
|
||||||
|
memLimit = bytesToGb(s.Deploy.Resources.Limits.MemoryBytes)
|
||||||
|
if !hasMemoryRequest() {
|
||||||
|
memRequest = memLimit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s.Deploy.Resources.Limits.NanoCPUs != "" {
|
||||||
|
cpuLimit, err = strconv.ParseFloat(s.Deploy.Resources.Limits.NanoCPUs, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !hasCPURequest() {
|
||||||
|
cpuRequest = cpuLimit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resources := containerinstance.ResourceRequirements{
|
||||||
|
Requests: &containerinstance.ResourceRequests{
|
||||||
|
MemoryInGB: to.Float64Ptr(memRequest),
|
||||||
|
CPU: to.Float64Ptr(cpuRequest),
|
||||||
|
},
|
||||||
Limits: &containerinstance.ResourceLimits{
|
Limits: &containerinstance.ResourceLimits{
|
||||||
MemoryInGB: to.Float64Ptr(memLimit),
|
MemoryInGB: to.Float64Ptr(memLimit),
|
||||||
CPU: to.Float64Ptr(cpuLimit),
|
CPU: to.Float64Ptr(cpuLimit),
|
||||||
},
|
},
|
||||||
Requests: &containerinstance.ResourceRequests{
|
}
|
||||||
MemoryInGB: to.Float64Ptr(memLimit), // TODO: use the memory requests here and not limits
|
return &resources, nil
|
||||||
CPU: to.Float64Ptr(cpuLimit), // TODO: use the cpu requests here and not limits
|
|
||||||
},
|
|
||||||
},
|
|
||||||
VolumeMounts: volumes,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEnvVariables(composeEnv types.MappingWithEquals) *[]containerinstance.EnvironmentVariable {
|
func getEnvVariables(composeEnv types.MappingWithEquals) *[]containerinstance.EnvironmentVariable {
|
||||||
@ -413,6 +444,10 @@ func bytesToGb(b types.UnitBytes) float64 {
|
|||||||
return math.Round(f*100) / 100
|
return math.Round(f*100) / 100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func gbToBytes(memInBytes float64) uint64 {
|
||||||
|
return uint64(memInBytes * 1024 * 1024 * 1024)
|
||||||
|
}
|
||||||
|
|
||||||
// ContainerGroupToServiceStatus convert from an ACI container definition to service status
|
// ContainerGroupToServiceStatus convert from an ACI container definition to service status
|
||||||
func ContainerGroupToServiceStatus(containerID string, group containerinstance.ContainerGroup, container containerinstance.Container, region string) compose.ServiceStatus {
|
func ContainerGroupToServiceStatus(containerID string, group containerinstance.ContainerGroup, container containerinstance.Container, region string) compose.ServiceStatus {
|
||||||
var replicas = 1
|
var replicas = 1
|
||||||
@ -438,19 +473,28 @@ func fqdn(group containerinstance.ContainerGroup, region string) string {
|
|||||||
|
|
||||||
// ContainerGroupToContainer composes a Container from an ACI container definition
|
// ContainerGroupToContainer composes a Container from an ACI container definition
|
||||||
func ContainerGroupToContainer(containerID string, cg containerinstance.ContainerGroup, cc containerinstance.Container, region string) containers.Container {
|
func ContainerGroupToContainer(containerID string, cg containerinstance.ContainerGroup, cc containerinstance.Container, region string) containers.Container {
|
||||||
memLimits := 0.
|
memLimits := uint64(0)
|
||||||
if cc.Resources != nil &&
|
memRequest := uint64(0)
|
||||||
cc.Resources.Limits != nil &&
|
|
||||||
cc.Resources.Limits.MemoryInGB != nil {
|
|
||||||
memLimits = *cc.Resources.Limits.MemoryInGB * 1024 * 1024 * 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
cpuLimit := 0.
|
cpuLimit := 0.
|
||||||
if cc.Resources != nil &&
|
cpuReservation := 0.
|
||||||
cc.Resources.Limits != nil &&
|
if cc.Resources != nil {
|
||||||
cc.Resources.Limits.CPU != nil {
|
if cc.Resources.Limits != nil {
|
||||||
|
if cc.Resources.Limits.MemoryInGB != nil {
|
||||||
|
memLimits = gbToBytes(*cc.Resources.Limits.MemoryInGB)
|
||||||
|
}
|
||||||
|
if cc.Resources.Limits.CPU != nil {
|
||||||
cpuLimit = *cc.Resources.Limits.CPU
|
cpuLimit = *cc.Resources.Limits.CPU
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if cc.Resources.Requests != nil {
|
||||||
|
if cc.Resources.Requests.MemoryInGB != nil {
|
||||||
|
memRequest = gbToBytes(*cc.Resources.Requests.MemoryInGB)
|
||||||
|
}
|
||||||
|
if cc.Resources.Requests.CPU != nil {
|
||||||
|
cpuReservation = *cc.Resources.Requests.CPU
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
command := ""
|
command := ""
|
||||||
if cc.Command != nil {
|
if cc.Command != nil {
|
||||||
@ -468,9 +512,16 @@ func ContainerGroupToContainer(containerID string, cg containerinstance.Containe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var config *containers.RuntimeConfig = &containers.RuntimeConfig{FQDN: fqdn(cg, region)}
|
config := &containers.RuntimeConfig{
|
||||||
if envVars != nil {
|
FQDN: fqdn(cg, region),
|
||||||
config.Env = envVars
|
Env: envVars,
|
||||||
|
}
|
||||||
|
hostConfig := &containers.HostConfig{
|
||||||
|
CPULimit: cpuLimit,
|
||||||
|
CPUReservation: cpuReservation,
|
||||||
|
MemoryLimit: memLimits,
|
||||||
|
MemoryReservation: memRequest,
|
||||||
|
RestartPolicy: toContainerRestartPolicy(cg.RestartPolicy),
|
||||||
}
|
}
|
||||||
c := containers.Container{
|
c := containers.Container{
|
||||||
ID: containerID,
|
ID: containerID,
|
||||||
@ -478,16 +529,13 @@ func ContainerGroupToContainer(containerID string, cg containerinstance.Containe
|
|||||||
Image: to.String(cc.Image),
|
Image: to.String(cc.Image),
|
||||||
Command: command,
|
Command: command,
|
||||||
CPUTime: 0,
|
CPUTime: 0,
|
||||||
CPULimit: cpuLimit,
|
|
||||||
MemoryUsage: 0,
|
MemoryUsage: 0,
|
||||||
MemoryLimit: uint64(memLimits),
|
|
||||||
PidsCurrent: 0,
|
PidsCurrent: 0,
|
||||||
PidsLimit: 0,
|
PidsLimit: 0,
|
||||||
Labels: nil,
|
|
||||||
Ports: ToPorts(cg.IPAddress, *cc.Ports),
|
Ports: ToPorts(cg.IPAddress, *cc.Ports),
|
||||||
Platform: platform,
|
Platform: platform,
|
||||||
RestartPolicyCondition: toContainerRestartPolicy(cg.RestartPolicy),
|
|
||||||
Config: config,
|
Config: config,
|
||||||
|
HostConfig: hostConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
@ -83,6 +83,10 @@ func TestContainerGroupToContainer(t *testing.T) {
|
|||||||
Resources: &containerinstance.ResourceRequirements{
|
Resources: &containerinstance.ResourceRequirements{
|
||||||
Limits: &containerinstance.ResourceLimits{
|
Limits: &containerinstance.ResourceLimits{
|
||||||
CPU: to.Float64Ptr(3),
|
CPU: to.Float64Ptr(3),
|
||||||
|
MemoryInGB: to.Float64Ptr(0.2),
|
||||||
|
},
|
||||||
|
Requests: &containerinstance.ResourceRequests{
|
||||||
|
CPU: to.Float64Ptr(2),
|
||||||
MemoryInGB: to.Float64Ptr(0.1),
|
MemoryInGB: to.Float64Ptr(0.1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -94,8 +98,6 @@ func TestContainerGroupToContainer(t *testing.T) {
|
|||||||
Status: "Running",
|
Status: "Running",
|
||||||
Image: "sha256:666",
|
Image: "sha256:666",
|
||||||
Command: "mycommand",
|
Command: "mycommand",
|
||||||
CPULimit: 3,
|
|
||||||
MemoryLimit: 107374182,
|
|
||||||
Platform: "Linux",
|
Platform: "Linux",
|
||||||
Ports: []containers.Port{{
|
Ports: []containers.Port{{
|
||||||
HostPort: uint32(80),
|
HostPort: uint32(80),
|
||||||
@ -106,7 +108,13 @@ func TestContainerGroupToContainer(t *testing.T) {
|
|||||||
Config: &containers.RuntimeConfig{
|
Config: &containers.RuntimeConfig{
|
||||||
FQDN: "myapp.eastus.azurecontainer.io",
|
FQDN: "myapp.eastus.azurecontainer.io",
|
||||||
},
|
},
|
||||||
RestartPolicyCondition: "any",
|
HostConfig: &containers.HostConfig{
|
||||||
|
CPULimit: 3,
|
||||||
|
CPUReservation: 2,
|
||||||
|
MemoryLimit: gbToBytes(0.2),
|
||||||
|
MemoryReservation: gbToBytes(0.1),
|
||||||
|
RestartPolicy: "any",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
container := ContainerGroupToContainer("myContainerID", myContainerGroup, myContainer, "eastus")
|
container := ContainerGroupToContainer("myContainerID", myContainerGroup, myContainer, "eastus")
|
||||||
@ -536,8 +544,9 @@ func TestComposeContainerGroupToContainerIgnoreDomainNameWithoutPorts(t *testing
|
|||||||
assert.Assert(t, group.IPAddress == nil)
|
assert.Assert(t, group.IPAddress == nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComposeContainerGroupToContainerResourceLimits(t *testing.T) {
|
var _0_1Gb = gbToBytes(0.1)
|
||||||
_0_1Gb := 0.1 * 1024 * 1024 * 1024
|
|
||||||
|
func TestComposeContainerGroupToContainerResourceRequests(t *testing.T) {
|
||||||
project := types.Project{
|
project := types.Project{
|
||||||
Services: []types.ServiceConfig{
|
Services: []types.ServiceConfig{
|
||||||
{
|
{
|
||||||
@ -545,7 +554,7 @@ func TestComposeContainerGroupToContainerResourceLimits(t *testing.T) {
|
|||||||
Image: "image1",
|
Image: "image1",
|
||||||
Deploy: &types.DeployConfig{
|
Deploy: &types.DeployConfig{
|
||||||
Resources: types.Resources{
|
Resources: types.Resources{
|
||||||
Limits: &types.Resource{
|
Reservations: &types.Resource{
|
||||||
NanoCPUs: "0.1",
|
NanoCPUs: "0.1",
|
||||||
MemoryBytes: types.UnitBytes(_0_1Gb),
|
MemoryBytes: types.UnitBytes(_0_1Gb),
|
||||||
},
|
},
|
||||||
@ -558,12 +567,48 @@ func TestComposeContainerGroupToContainerResourceLimits(t *testing.T) {
|
|||||||
group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
|
group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
request := *((*group.Containers)[0]).Resources.Requests
|
||||||
|
assert.Equal(t, *request.CPU, float64(0.1))
|
||||||
|
assert.Equal(t, *request.MemoryInGB, float64(0.1))
|
||||||
limits := *((*group.Containers)[0]).Resources.Limits
|
limits := *((*group.Containers)[0]).Resources.Limits
|
||||||
assert.Equal(t, *limits.CPU, float64(0.1))
|
assert.Equal(t, *limits.CPU, float64(0.1))
|
||||||
assert.Equal(t, *limits.MemoryInGB, float64(0.1))
|
assert.Equal(t, *limits.MemoryInGB, float64(0.1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComposeContainerGroupToContainerResourceLimitsDefaults(t *testing.T) {
|
func TestComposeContainerGroupToContainerResourceRequestsAndLimits(t *testing.T) {
|
||||||
|
project := types.Project{
|
||||||
|
Services: []types.ServiceConfig{
|
||||||
|
{
|
||||||
|
Name: "service1",
|
||||||
|
Image: "image1",
|
||||||
|
Deploy: &types.DeployConfig{
|
||||||
|
Resources: types.Resources{
|
||||||
|
Reservations: &types.Resource{
|
||||||
|
NanoCPUs: "0.1",
|
||||||
|
MemoryBytes: types.UnitBytes(_0_1Gb),
|
||||||
|
},
|
||||||
|
Limits: &types.Resource{
|
||||||
|
NanoCPUs: "0.3",
|
||||||
|
MemoryBytes: types.UnitBytes(2 * _0_1Gb),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
request := *((*group.Containers)[0]).Resources.Requests
|
||||||
|
assert.Equal(t, *request.CPU, float64(0.1))
|
||||||
|
assert.Equal(t, *request.MemoryInGB, float64(0.1))
|
||||||
|
limits := *((*group.Containers)[0]).Resources.Limits
|
||||||
|
assert.Equal(t, *limits.CPU, float64(0.3))
|
||||||
|
assert.Equal(t, *limits.MemoryInGB, float64(0.2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComposeContainerGroupToContainerResourceLimitsOnly(t *testing.T) {
|
||||||
project := types.Project{
|
project := types.Project{
|
||||||
Services: []types.ServiceConfig{
|
Services: []types.ServiceConfig{
|
||||||
{
|
{
|
||||||
@ -572,6 +617,35 @@ func TestComposeContainerGroupToContainerResourceLimitsDefaults(t *testing.T) {
|
|||||||
Deploy: &types.DeployConfig{
|
Deploy: &types.DeployConfig{
|
||||||
Resources: types.Resources{
|
Resources: types.Resources{
|
||||||
Limits: &types.Resource{
|
Limits: &types.Resource{
|
||||||
|
NanoCPUs: "0.3",
|
||||||
|
MemoryBytes: types.UnitBytes(2 * _0_1Gb),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
request := *((*group.Containers)[0]).Resources.Requests
|
||||||
|
assert.Equal(t, *request.CPU, float64(0.3))
|
||||||
|
assert.Equal(t, *request.MemoryInGB, float64(0.2))
|
||||||
|
limits := *((*group.Containers)[0]).Resources.Limits
|
||||||
|
assert.Equal(t, *limits.CPU, float64(0.3))
|
||||||
|
assert.Equal(t, *limits.MemoryInGB, float64(0.2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComposeContainerGroupToContainerResourceRequestsDefaults(t *testing.T) {
|
||||||
|
project := types.Project{
|
||||||
|
Services: []types.ServiceConfig{
|
||||||
|
{
|
||||||
|
Name: "service1",
|
||||||
|
Image: "image1",
|
||||||
|
Deploy: &types.DeployConfig{
|
||||||
|
Resources: types.Resources{
|
||||||
|
Reservations: &types.Resource{
|
||||||
NanoCPUs: "",
|
NanoCPUs: "",
|
||||||
MemoryBytes: 0,
|
MemoryBytes: 0,
|
||||||
},
|
},
|
||||||
@ -584,9 +658,9 @@ func TestComposeContainerGroupToContainerResourceLimitsDefaults(t *testing.T) {
|
|||||||
group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
|
group, err := ToContainerGroup(context.TODO(), convertCtx, project, mockStorageHelper)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
limits := *((*group.Containers)[0]).Resources.Limits
|
request := *((*group.Containers)[0]).Resources.Requests
|
||||||
assert.Equal(t, *limits.CPU, float64(1))
|
assert.Equal(t, *request.CPU, float64(1))
|
||||||
assert.Equal(t, *limits.MemoryInGB, float64(1))
|
assert.Equal(t, *request.MemoryInGB, float64(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComposeContainerGroupToContainerenvVar(t *testing.T) {
|
func TestComposeContainerGroupToContainerenvVar(t *testing.T) {
|
||||||
|
@ -42,25 +42,32 @@ type Container struct {
|
|||||||
Image string
|
Image string
|
||||||
Command string
|
Command string
|
||||||
CPUTime uint64
|
CPUTime uint64
|
||||||
CPULimit float64
|
|
||||||
MemoryUsage uint64
|
MemoryUsage uint64
|
||||||
MemoryLimit uint64
|
|
||||||
PidsCurrent uint64
|
PidsCurrent uint64
|
||||||
PidsLimit uint64
|
PidsLimit uint64
|
||||||
Config *RuntimeConfig `json:",omitempty"`
|
Config *RuntimeConfig `json:",omitempty"`
|
||||||
Labels []string `json:",omitempty"`
|
HostConfig *HostConfig `json:",omitempty"`
|
||||||
Ports []Port `json:",omitempty"`
|
Ports []Port `json:",omitempty"`
|
||||||
Platform string
|
Platform string
|
||||||
RestartPolicyCondition string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeConfig config of a created container
|
// RuntimeConfig config of a created container
|
||||||
type RuntimeConfig struct {
|
type RuntimeConfig struct {
|
||||||
|
Labels []string `json:",omitempty"`
|
||||||
Env map[string]string `json:",omitempty"`
|
Env map[string]string `json:",omitempty"`
|
||||||
// FQDN is the fqdn to use
|
// FQDN is the fqdn to use
|
||||||
FQDN string `json:"fqdn,omitempty"`
|
FQDN string `json:"fqdn,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HostConfig config of the container host
|
||||||
|
type HostConfig struct {
|
||||||
|
RestartPolicy string
|
||||||
|
CPUReservation float64
|
||||||
|
CPULimit float64
|
||||||
|
MemoryReservation uint64
|
||||||
|
MemoryLimit uint64
|
||||||
|
}
|
||||||
|
|
||||||
// Port represents a published port of a container
|
// Port represents a published port of a container
|
||||||
type Port struct {
|
type Port struct {
|
||||||
// HostPort is the port number on the host
|
// HostPort is the port number on the host
|
||||||
|
12
cli/cmd/testdata/inspect-out-id.golden
vendored
12
cli/cmd/testdata/inspect-out-id.golden
vendored
@ -4,11 +4,15 @@
|
|||||||
"Image": "nginx",
|
"Image": "nginx",
|
||||||
"Command": "",
|
"Command": "",
|
||||||
"CPUTime": 0,
|
"CPUTime": 0,
|
||||||
"CPULimit": 0,
|
|
||||||
"MemoryUsage": 0,
|
"MemoryUsage": 0,
|
||||||
"MemoryLimit": 0,
|
|
||||||
"PidsCurrent": 0,
|
"PidsCurrent": 0,
|
||||||
"PidsLimit": 0,
|
"PidsLimit": 0,
|
||||||
"Platform": "Linux",
|
"HostConfig": {
|
||||||
"RestartPolicyCondition": "none"
|
"RestartPolicy": "none",
|
||||||
|
"CPUReservation": 0,
|
||||||
|
"CPULimit": 0,
|
||||||
|
"MemoryReservation": 0,
|
||||||
|
"MemoryLimit": 0
|
||||||
|
},
|
||||||
|
"Platform": "Linux"
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,9 @@ func (cs *containerService) Inspect(ctx context.Context, id string) (containers.
|
|||||||
ID: "id",
|
ID: "id",
|
||||||
Image: "nginx",
|
Image: "nginx",
|
||||||
Platform: "Linux",
|
Platform: "Linux",
|
||||||
RestartPolicyCondition: "none",
|
HostConfig: &containers.HostConfig{
|
||||||
|
RestartPolicy: "none",
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -45,14 +45,20 @@ message Container {
|
|||||||
string command = 4;
|
string command = 4;
|
||||||
uint64 cpu_time = 5;
|
uint64 cpu_time = 5;
|
||||||
uint64 memory_usage = 6;
|
uint64 memory_usage = 6;
|
||||||
uint64 memory_limit = 7;
|
uint64 pids_current = 7;
|
||||||
uint64 pids_current = 8;
|
uint64 pids_limit = 8;
|
||||||
uint64 pids_limit = 9;
|
repeated string labels = 9;
|
||||||
repeated string labels = 10;
|
repeated Port ports = 10;
|
||||||
repeated Port ports = 11;
|
string platform = 11;
|
||||||
uint64 cpu_limit = 12;
|
HostConfig host_config = 12;
|
||||||
string platform = 13;
|
}
|
||||||
string restart_policy_condition = 14;
|
|
||||||
|
message HostConfig {
|
||||||
|
uint64 memory_reservation = 1;
|
||||||
|
uint64 memory_limit = 2;
|
||||||
|
uint64 cpu_reservation = 3;
|
||||||
|
uint64 cpu_limit = 4;
|
||||||
|
string restart_policy = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message InspectRequest {
|
message InspectRequest {
|
||||||
|
@ -128,14 +128,18 @@ func toGrpcContainer(c containers.Container) *containersv1.Container {
|
|||||||
Command: c.Command,
|
Command: c.Command,
|
||||||
CpuTime: c.CPUTime,
|
CpuTime: c.CPUTime,
|
||||||
MemoryUsage: c.MemoryUsage,
|
MemoryUsage: c.MemoryUsage,
|
||||||
MemoryLimit: c.MemoryLimit,
|
|
||||||
Platform: c.Platform,
|
Platform: c.Platform,
|
||||||
PidsCurrent: c.PidsCurrent,
|
PidsCurrent: c.PidsCurrent,
|
||||||
PidsLimit: c.PidsLimit,
|
PidsLimit: c.PidsLimit,
|
||||||
Labels: c.Labels,
|
Labels: c.Config.Labels,
|
||||||
Ports: portsToGrpc(c.Ports),
|
Ports: portsToGrpc(c.Ports),
|
||||||
CpuLimit: uint64(c.CPULimit),
|
HostConfig: &containersv1.HostConfig{
|
||||||
RestartPolicyCondition: c.RestartPolicyCondition,
|
MemoryReservation: c.HostConfig.MemoryReservation,
|
||||||
|
MemoryLimit: c.HostConfig.MemoryLimit,
|
||||||
|
CpuReservation: uint64(c.HostConfig.CPUReservation),
|
||||||
|
CpuLimit: uint64(c.HostConfig.CPULimit),
|
||||||
|
RestartPolicy: c.HostConfig.RestartPolicy,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,8 +249,9 @@ func TestRunVolume(t *testing.T) {
|
|||||||
containerInspect, err := ParseContainerInspect(res.Stdout())
|
containerInspect, err := ParseContainerInspect(res.Stdout())
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, containerInspect.Platform, "Linux")
|
assert.Equal(t, containerInspect.Platform, "Linux")
|
||||||
assert.Equal(t, containerInspect.CPULimit, 1.0)
|
assert.Equal(t, containerInspect.HostConfig.CPULimit, 1.0)
|
||||||
assert.Equal(t, containerInspect.RestartPolicyCondition, containers.RestartPolicyNone)
|
assert.Equal(t, containerInspect.HostConfig.CPUReservation, 1.0)
|
||||||
|
assert.Equal(t, containerInspect.HostConfig.RestartPolicy, containers.RestartPolicyNone)
|
||||||
|
|
||||||
assert.Assert(t, is.Len(containerInspect.Ports, 1))
|
assert.Assert(t, is.Len(containerInspect.Ports, 1))
|
||||||
hostIP = containerInspect.Ports[0].HostIP
|
hostIP = containerInspect.Ports[0].HostIP
|
||||||
@ -388,16 +389,18 @@ func TestContainerRunAttached(t *testing.T) {
|
|||||||
}
|
}
|
||||||
return poll.Continue("waiting for container to be running, current inspect result: \n%s", res.Combined())
|
return poll.Continue("waiting for container to be running, current inspect result: \n%s", res.Combined())
|
||||||
}
|
}
|
||||||
poll.WaitOn(t, checkRunning, poll.WithDelay(5*time.Second), poll.WithTimeout(60*time.Second))
|
poll.WaitOn(t, checkRunning, poll.WithDelay(5*time.Second), poll.WithTimeout(90*time.Second))
|
||||||
|
|
||||||
inspectRes := c.RunDockerCmd("inspect", container)
|
inspectRes := c.RunDockerCmd("inspect", container)
|
||||||
|
|
||||||
containerInspect, err := ParseContainerInspect(inspectRes.Stdout())
|
containerInspect, err := ParseContainerInspect(inspectRes.Stdout())
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, containerInspect.Platform, "Linux")
|
assert.Equal(t, containerInspect.Platform, "Linux")
|
||||||
assert.Equal(t, containerInspect.CPULimit, 0.1)
|
assert.Equal(t, containerInspect.HostConfig.CPULimit, 0.1)
|
||||||
assert.Equal(t, containerInspect.MemoryLimit, uint64(107374182))
|
assert.Equal(t, containerInspect.HostConfig.MemoryLimit, uint64(107374182))
|
||||||
assert.Equal(t, containerInspect.RestartPolicyCondition, containers.RestartPolicyOnFailure)
|
assert.Equal(t, containerInspect.HostConfig.CPUReservation, 0.1)
|
||||||
|
assert.Equal(t, containerInspect.HostConfig.MemoryReservation, uint64(107374182))
|
||||||
|
assert.Equal(t, containerInspect.HostConfig.RestartPolicy, containers.RestartPolicyOnFailure)
|
||||||
|
|
||||||
assert.Assert(t, is.Len(containerInspect.Ports, 1))
|
assert.Assert(t, is.Len(containerInspect.Ports, 1))
|
||||||
port := containerInspect.Ports[0]
|
port := containerInspect.Ports[0]
|
||||||
@ -480,6 +483,39 @@ func overwriteFileStorageAccount(t *testing.T, absComposefileName string, storag
|
|||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpResources(t *testing.T) {
|
||||||
|
const (
|
||||||
|
composeProjectName = "testresources"
|
||||||
|
serverContainer = composeProjectName + "_web"
|
||||||
|
wordsContainer = composeProjectName + "_words"
|
||||||
|
)
|
||||||
|
|
||||||
|
c := NewParallelE2eCLI(t, binDir)
|
||||||
|
setupTestResourceGroup(t, c)
|
||||||
|
|
||||||
|
t.Run("compose up", func(t *testing.T) {
|
||||||
|
c.RunDockerCmd("compose", "up", "-f", "../composefiles/aci-demo/aci_demo_port_resources.yaml", "--project-name", composeProjectName)
|
||||||
|
|
||||||
|
res := c.RunDockerCmd("inspect", serverContainer)
|
||||||
|
|
||||||
|
webInspect, err := ParseContainerInspect(res.Stdout())
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, webInspect.HostConfig.CPULimit, 0.7)
|
||||||
|
assert.Equal(t, webInspect.HostConfig.MemoryLimit, uint64(1073741824))
|
||||||
|
assert.Equal(t, webInspect.HostConfig.CPUReservation, 0.5)
|
||||||
|
assert.Equal(t, webInspect.HostConfig.MemoryReservation, uint64(536870912))
|
||||||
|
|
||||||
|
res = c.RunDockerCmd("inspect", wordsContainer)
|
||||||
|
|
||||||
|
wordsInspect, err := ParseContainerInspect(res.Stdout())
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, wordsInspect.HostConfig.CPULimit, 0.5)
|
||||||
|
assert.Equal(t, wordsInspect.HostConfig.MemoryLimit, uint64(751619276))
|
||||||
|
assert.Equal(t, wordsInspect.HostConfig.CPUReservation, 0.5)
|
||||||
|
assert.Equal(t, wordsInspect.HostConfig.MemoryReservation, uint64(751619276))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestUpUpdate(t *testing.T) {
|
func TestUpUpdate(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
composeProjectName = "acidemo"
|
composeProjectName = "acidemo"
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
services:
|
|
||||||
db:
|
|
||||||
build: db
|
|
||||||
image: gtardif/sentences-db
|
|
||||||
|
|
||||||
words:
|
|
||||||
build: words
|
|
||||||
image: gtardif/sentences-api
|
|
||||||
|
|
||||||
web:
|
|
||||||
build: web
|
|
||||||
image: gtardif/sentences-web
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
24
tests/composefiles/aci-demo/aci_demo_port_resources.yaml
Normal file
24
tests/composefiles/aci-demo/aci_demo_port_resources.yaml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: gtardif/sentences-db
|
||||||
|
|
||||||
|
words:
|
||||||
|
image: gtardif/sentences-api
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
reservations:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 0.7G
|
||||||
|
|
||||||
|
web:
|
||||||
|
image: gtardif/sentences-web
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.7'
|
||||||
|
memory: 1G
|
||||||
|
reservations:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 0.5G
|
12
tests/e2e/testdata/inspect-id.golden
vendored
12
tests/e2e/testdata/inspect-id.golden
vendored
@ -4,11 +4,15 @@
|
|||||||
"Image": "nginx",
|
"Image": "nginx",
|
||||||
"Command": "",
|
"Command": "",
|
||||||
"CPUTime": 0,
|
"CPUTime": 0,
|
||||||
"CPULimit": 0,
|
|
||||||
"MemoryUsage": 0,
|
"MemoryUsage": 0,
|
||||||
"MemoryLimit": 0,
|
|
||||||
"PidsCurrent": 0,
|
"PidsCurrent": 0,
|
||||||
"PidsLimit": 0,
|
"PidsLimit": 0,
|
||||||
"Platform": "Linux",
|
"HostConfig": {
|
||||||
"RestartPolicyCondition": "none"
|
"RestartPolicy": "none",
|
||||||
|
"CPUReservation": 0,
|
||||||
|
"CPULimit": 0,
|
||||||
|
"MemoryReservation": 0,
|
||||||
|
"MemoryLimit": 0
|
||||||
|
},
|
||||||
|
"Platform": "Linux"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user