diff --git a/ecs/cloudformation.go b/ecs/cloudformation.go index 16c330741..3fe1168ac 100644 --- a/ecs/cloudformation.go +++ b/ecs/cloudformation.go @@ -277,7 +277,7 @@ func (b *ecsAPIService) convert(project *types.Project) (*cloudformation.Templat LoadBalancers: serviceLB, NetworkConfiguration: &ecs.Service_NetworkConfiguration{ AwsvpcConfiguration: &ecs.Service_AwsVpcConfiguration{ - AssignPublicIp: ecsapi.AssignPublicIpDisabled, + AssignPublicIp: ecsapi.AssignPublicIpEnabled, SecurityGroups: serviceSecurityGroups, Subnets: []string{ cloudformation.Ref(parameterSubnet1Id), diff --git a/ecs/cloudformation_test.go b/ecs/cloudformation_test.go index c21508151..1831ef6b1 100644 --- a/ecs/cloudformation_test.go +++ b/ecs/cloudformation_test.go @@ -245,6 +245,15 @@ services: func TestTaskSizeConvert(t *testing.T) { template := convertYaml(t, ` +services: + test: + image: nginx +`) + def := template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition) + assert.Equal(t, def.Cpu, "256") + assert.Equal(t, def.Memory, "512") + + template = convertYaml(t, ` services: test: image: nginx @@ -253,11 +262,8 @@ services: limits: cpus: '0.5' memory: 2048M - reservations: - cpus: '0.5' - memory: 2048M `) - def := template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition) + def = template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition) assert.Equal(t, def.Cpu, "512") assert.Equal(t, def.Memory, "2048") @@ -270,13 +276,29 @@ services: limits: cpus: '4' memory: 8192M - reservations: - cpus: '4' - memory: 8192M `) def = template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition) assert.Equal(t, def.Cpu, "4096") assert.Equal(t, def.Memory, "8192") + + template = convertYaml(t, ` +services: + test: + image: nginx + deploy: + resources: + limits: + cpus: '4' + memory: 792Mb + reservations: + generic_resources: + - discrete_resource_spec: + kind: gpus + value: 2 +`) + def = template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition) + assert.Equal(t, def.Cpu, "4000") + assert.Equal(t, def.Memory, "792") } func TestTaskSizeConvertFailure(t *testing.T) { model := loadConfig(t, ` diff --git a/ecs/convert.go b/ecs/convert.go index 4ceb50389..e878e930d 100644 --- a/ecs/convert.go +++ b/ecs/convert.go @@ -323,8 +323,17 @@ func toSystemControls(sysctls types.Mapping) []ecs.TaskDefinition_SystemControl const miB = 1024 * 1024 func toLimits(service types.ServiceConfig) (string, string, error) { - // All possible CPU/mem values for Fargate - cpuToMem := map[int64][]types.UnitBytes{ + mem, cpu, err := getConfiguredLimits(service) + if err != nil { + return "", "", err + } + if requireEC2(service) { + // just return configured limits expressed in Mb and CPU units + return fmt.Sprint(cpu), fmt.Sprint(mem / miB), nil + } + + // All possible cpu/mem values for Fargate + fargateCPUToMem := map[int64][]types.UnitBytes{ 256: {512, 1024, 2048}, 512: {1024, 2048, 3072, 4096}, 1024: {2048, 3072, 4096, 5120, 6144, 7168, 8192}, @@ -333,37 +342,22 @@ func toLimits(service types.ServiceConfig) (string, string, error) { } cpuLimit := "256" memLimit := "512" - - if service.Deploy == nil { + if mem == 0 && cpu == 0 { return cpuLimit, memLimit, nil } - limits := service.Deploy.Resources.Limits - if limits == nil { - return cpuLimit, memLimit, nil - } - - if limits.NanoCPUs == "" { - return cpuLimit, memLimit, nil - } - - v, err := opts.ParseCPUs(limits.NanoCPUs) - if err != nil { - return "", "", err - } - var cpus []int64 - for k := range cpuToMem { + for k := range fargateCPUToMem { cpus = append(cpus, k) } sort.Slice(cpus, func(i, j int) bool { return cpus[i] < cpus[j] }) - for _, cpu := range cpus { - mem := cpuToMem[cpu] - if v <= cpu*miB { - for _, m := range mem { - if limits.MemoryBytes <= m*miB { - cpuLimit = strconv.FormatInt(cpu, 10) + for _, fargateCPU := range cpus { + options := fargateCPUToMem[fargateCPU] + if cpu <= fargateCPU { + for _, m := range options { + if mem <= m*miB { + cpuLimit = strconv.FormatInt(fargateCPU, 10) memLimit = strconv.FormatInt(int64(m), 10) return cpuLimit, memLimit, nil } @@ -373,6 +367,27 @@ func toLimits(service types.ServiceConfig) (string, string, error) { return "", "", fmt.Errorf("the resources requested are not supported by ECS/Fargate") } +func getConfiguredLimits(service types.ServiceConfig) (types.UnitBytes, int64, error) { + if service.Deploy == nil { + return 0, 0, nil + } + + limits := service.Deploy.Resources.Limits + if limits == nil { + return 0, 0, nil + } + + if limits.NanoCPUs == "" { + return limits.MemoryBytes, 0, nil + } + v, err := opts.ParseCPUs(limits.NanoCPUs) + if err != nil { + return 0, 0, err + } + + return limits.MemoryBytes, v / 1e6, nil +} + func toContainerReservation(service types.ServiceConfig) (string, int) { cpuReservation := ".0" memReservation := 0 diff --git a/ecs/sdk.go b/ecs/sdk.go index 135ec20d7..906e2d427 100644 --- a/ecs/sdk.go +++ b/ecs/sdk.go @@ -92,7 +92,7 @@ func (s sdk) CheckRequirements(ctx context.Context, region string) error { if *serviceLongArnFormat != "enabled" { return fmt.Errorf("this tool requires the \"new ARN resource ID format\".\n"+ "Check https://%s.console.aws.amazon.com/ecs/home#/settings\n"+ - "Learn more: https://aws.amazon.com/blogs/compute/migrating-your-amazon-ecs-deployment-to-the-new-arn-and-resource-ID-format-2", region) + "Learn more: https://aws.amazon.com/blogs/compute/migrating-your-amazon-ecs-deployment-to-the-new-arn-and-resource-id-format-2", region) } return nil } diff --git a/ecs/tags.go b/ecs/tags.go index 74c03158e..01dead2f2 100644 --- a/ecs/tags.go +++ b/ecs/tags.go @@ -1,5 +1,5 @@ /* - Copyright 2020 Docker, Inc. + Copyright 2020 Docker Compose CLI authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/ecs/testdata/simple/simple-cloudformation-conversion.golden b/ecs/testdata/simple/simple-cloudformation-conversion.golden index cbda1f5a7..c977241c4 100644 --- a/ecs/testdata/simple/simple-cloudformation-conversion.golden +++ b/ecs/testdata/simple/simple-cloudformation-conversion.golden @@ -107,7 +107,7 @@ ], "NetworkConfiguration": { "AwsvpcConfiguration": { - "AssignPublicIp": "DISABLED", + "AssignPublicIp": "ENABLED", "SecurityGroups": [ { "Ref": "TestSimpleConvertDefaultNetwork"