Procházet zdrojové kódy

Allow to set memory / CPU limits higher than requests, ACI will request that limits are not higher than the total request for the container group. Also set requests = limits when only limits are set

Signed-off-by: Guillaume Tardif <[email protected]>
Guillaume Tardif před 5 roky
rodič
revize
343d54dac5
2 změnil soubory, kde provedl 125 přidání a 19 odebrání
  1. 58 19
      aci/convert/convert.go
  2. 67 0
      aci/convert/convert_test.go

+ 58 - 19
aci/convert/convert.go

@@ -353,36 +353,75 @@ func (s serviceConfigAciHelper) getAciContainer(volumesCache map[string]bool) (c
 		volumes = &allVolumes
 	}
 
-	memRequest := 1. // Default 1 Gb
-	var cpuRequest float64 = 1
-	if s.Deploy != nil && s.Deploy.Resources.Reservations != nil {
-		if s.Deploy.Resources.Reservations.MemoryBytes != 0 {
-			memRequest = bytesToGb(s.Deploy.Resources.Reservations.MemoryBytes)
-		}
-		if s.Deploy.Resources.Reservations.NanoCPUs != "" {
-			cpuRequest, err = strconv.ParseFloat(s.Deploy.Resources.Reservations.NanoCPUs, 0)
-			if err != nil {
-				return containerinstance.Container{}, err
-			}
-		}
+	resource, err := s.getResourceRequestsLimits()
+	if err != nil {
+		return containerinstance.Container{}, err
 	}
+
 	return containerinstance.Container{
 		Name: to.StringPtr(s.Name),
 		ContainerProperties: &containerinstance.ContainerProperties{
 			Image:                to.StringPtr(s.Image),
 			Command:              to.StringSlicePtr(s.Command),
 			EnvironmentVariables: getEnvVariables(s.Environment),
-			Resources: &containerinstance.ResourceRequirements{
-				Requests: &containerinstance.ResourceRequests{
-					MemoryInGB: to.Float64Ptr(memRequest),
-					CPU:        to.Float64Ptr(cpuRequest),
-				},
-			},
-			VolumeMounts: volumes,
+			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{
+			MemoryInGB: to.Float64Ptr(memLimit),
+			CPU:        to.Float64Ptr(cpuLimit),
+		},
+	}
+	return &resources, nil
+}
+
 func getEnvVariables(composeEnv types.MappingWithEquals) *[]containerinstance.EnvironmentVariable {
 	result := []containerinstance.EnvironmentVariable{}
 	for key, value := range composeEnv {

+ 67 - 0
aci/convert/convert_test.go

@@ -561,6 +561,73 @@ func TestComposeContainerGroupToContainerResourceRequests(t *testing.T) {
 	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.1))
+	assert.Equal(t, *limits.MemoryInGB, float64(0.1))
+}
+
+func TestComposeContainerGroupToContainerResourceRequestsAndLimits(t *testing.T) {
+	_0_1Gb := 0.1 * 1024 * 1024 * 1024
+	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) {
+	_0_1Gb := 0.1 * 1024 * 1024 * 1024
+	project := types.Project{
+		Services: []types.ServiceConfig{
+			{
+				Name:  "service1",
+				Image: "image1",
+				Deploy: &types.DeployConfig{
+					Resources: types.Resources{
+						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) {