2020-08-18 11:38:23 +02:00
|
|
|
/*
|
2020-09-22 12:13:00 +02:00
|
|
|
Copyright 2020 Docker Compose CLI authors
|
2020-08-18 11:38:23 +02:00
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2020-08-17 17:48:52 +02:00
|
|
|
package ecs
|
2020-05-13 18:02:52 +02:00
|
|
|
|
|
|
|
import (
|
2020-10-12 16:21:48 +02:00
|
|
|
"context"
|
2020-05-13 18:02:52 +02:00
|
|
|
"fmt"
|
2020-10-12 16:21:48 +02:00
|
|
|
"io/ioutil"
|
2020-06-30 15:52:04 +02:00
|
|
|
"reflect"
|
2020-05-13 18:02:52 +02:00
|
|
|
"testing"
|
|
|
|
|
2021-06-14 16:26:14 +02:00
|
|
|
"github.com/docker/compose-cli/pkg/api"
|
2020-08-18 11:38:23 +02:00
|
|
|
|
2020-06-08 15:34:33 +02:00
|
|
|
"github.com/aws/aws-sdk-go/service/elbv2"
|
2020-06-08 09:16:58 +02:00
|
|
|
"github.com/awslabs/goformation/v4/cloudformation"
|
2020-06-08 11:28:15 +02:00
|
|
|
"github.com/awslabs/goformation/v4/cloudformation/ec2"
|
2020-06-30 17:15:52 +02:00
|
|
|
"github.com/awslabs/goformation/v4/cloudformation/ecs"
|
2020-09-29 15:11:31 +02:00
|
|
|
"github.com/awslabs/goformation/v4/cloudformation/efs"
|
2020-06-08 15:34:33 +02:00
|
|
|
"github.com/awslabs/goformation/v4/cloudformation/elasticloadbalancingv2"
|
2020-06-17 14:48:42 +02:00
|
|
|
"github.com/awslabs/goformation/v4/cloudformation/iam"
|
2020-08-11 15:48:12 +02:00
|
|
|
"github.com/awslabs/goformation/v4/cloudformation/logs"
|
2020-06-08 09:16:58 +02:00
|
|
|
"github.com/compose-spec/compose-go/loader"
|
|
|
|
"github.com/compose-spec/compose-go/types"
|
2020-09-29 15:11:31 +02:00
|
|
|
"github.com/golang/mock/gomock"
|
2020-06-10 10:42:48 +02:00
|
|
|
"gotest.tools/v3/assert"
|
2020-05-13 18:02:52 +02:00
|
|
|
"gotest.tools/v3/golden"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestSimpleConvert(t *testing.T) {
|
2020-10-12 16:21:48 +02:00
|
|
|
bytes, err := ioutil.ReadFile("testdata/input/simple-single-service.yaml")
|
|
|
|
assert.NilError(t, err)
|
|
|
|
template := convertYaml(t, string(bytes), useDefaultVPC)
|
2020-11-05 09:27:14 +01:00
|
|
|
resultAsJSON, err := marshall(template, "yaml")
|
2020-10-12 16:21:48 +02:00
|
|
|
assert.NilError(t, err)
|
|
|
|
result := fmt.Sprintf("%s\n", string(resultAsJSON))
|
2021-02-02 15:44:37 +01:00
|
|
|
expected := "simple-cloudformation-conversion.golden"
|
2020-05-13 18:02:52 +02:00
|
|
|
golden.Assert(t, result, expected)
|
|
|
|
}
|
|
|
|
|
2020-08-11 15:48:12 +02:00
|
|
|
func TestLogging(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-08-11 15:48:12 +02:00
|
|
|
services:
|
|
|
|
foo:
|
|
|
|
image: hello_world
|
|
|
|
logging:
|
|
|
|
options:
|
|
|
|
awslogs-datetime-pattern: "FOO"
|
|
|
|
|
|
|
|
x-aws-logs_retention: 10
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-08-11 15:48:12 +02:00
|
|
|
def := template.Resources["FooTaskDefinition"].(*ecs.TaskDefinition)
|
2020-09-28 13:36:12 +02:00
|
|
|
logging := getMainContainer(def, t).LogConfiguration
|
|
|
|
if logging != nil {
|
|
|
|
assert.Equal(t, logging.Options["awslogs-datetime-pattern"], "FOO")
|
|
|
|
} else {
|
|
|
|
t.Fatal("Logging not configured")
|
|
|
|
}
|
2020-08-11 15:48:12 +02:00
|
|
|
|
|
|
|
logGroup := template.Resources["LogGroup"].(*logs.LogGroup)
|
|
|
|
assert.Equal(t, logGroup.RetentionInDays, 10)
|
|
|
|
}
|
|
|
|
|
2020-08-11 15:48:12 +02:00
|
|
|
func TestEnvFile(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-08-11 15:48:12 +02:00
|
|
|
services:
|
|
|
|
foo:
|
|
|
|
image: hello_world
|
|
|
|
env_file:
|
|
|
|
- testdata/input/envfile
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-08-11 15:48:12 +02:00
|
|
|
def := template.Resources["FooTaskDefinition"].(*ecs.TaskDefinition)
|
2020-09-28 13:36:12 +02:00
|
|
|
env := getMainContainer(def, t).Environment
|
2020-08-11 15:48:12 +02:00
|
|
|
var found bool
|
|
|
|
for _, pair := range env {
|
|
|
|
if pair.Name == "FOO" {
|
|
|
|
assert.Equal(t, pair.Value, "BAR")
|
|
|
|
found = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert.Check(t, found, "environment variable FOO not set")
|
2020-08-11 15:48:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEnvFileAndEnv(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-08-11 15:48:12 +02:00
|
|
|
services:
|
|
|
|
foo:
|
|
|
|
image: hello_world
|
|
|
|
env_file:
|
|
|
|
- testdata/input/envfile
|
|
|
|
environment:
|
|
|
|
- "FOO=ZOT"
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-08-11 15:48:12 +02:00
|
|
|
def := template.Resources["FooTaskDefinition"].(*ecs.TaskDefinition)
|
2020-09-28 13:36:12 +02:00
|
|
|
env := getMainContainer(def, t).Environment
|
2020-08-12 14:45:10 +02:00
|
|
|
var found bool
|
|
|
|
for _, pair := range env {
|
|
|
|
if pair.Name == "FOO" {
|
|
|
|
assert.Equal(t, pair.Value, "ZOT")
|
|
|
|
found = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert.Check(t, found, "environment variable FOO not set")
|
2020-08-11 15:48:12 +02:00
|
|
|
}
|
|
|
|
|
2020-08-11 11:19:58 +02:00
|
|
|
func TestRollingUpdateLimits(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-08-11 11:19:58 +02:00
|
|
|
services:
|
|
|
|
foo:
|
|
|
|
image: hello_world
|
|
|
|
deploy:
|
|
|
|
replicas: 4
|
|
|
|
update_config:
|
|
|
|
parallelism: 2
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-08-11 11:19:58 +02:00
|
|
|
service := template.Resources["FooService"].(*ecs.Service)
|
|
|
|
assert.Check(t, service.DeploymentConfiguration.MaximumPercent == 150)
|
|
|
|
assert.Check(t, service.DeploymentConfiguration.MinimumHealthyPercent == 50)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRollingUpdateExtension(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-08-11 11:19:58 +02:00
|
|
|
services:
|
|
|
|
foo:
|
|
|
|
image: hello_world
|
|
|
|
deploy:
|
|
|
|
update_config:
|
|
|
|
x-aws-min_percent: 25
|
|
|
|
x-aws-max_percent: 125
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-08-11 11:19:58 +02:00
|
|
|
service := template.Resources["FooService"].(*ecs.Service)
|
|
|
|
assert.Check(t, service.DeploymentConfiguration.MaximumPercent == 125)
|
|
|
|
assert.Check(t, service.DeploymentConfiguration.MinimumHealthyPercent == 25)
|
|
|
|
}
|
|
|
|
|
2020-06-08 11:28:15 +02:00
|
|
|
func TestRolePolicy(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-06-08 11:28:15 +02:00
|
|
|
services:
|
|
|
|
foo:
|
|
|
|
image: hello_world
|
|
|
|
x-aws-pull_credentials: "secret"
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-08-18 16:56:42 +02:00
|
|
|
x := template.Resources["FooTaskExecutionRole"]
|
|
|
|
assert.Check(t, x != nil)
|
|
|
|
role := *(x.(*iam.Role))
|
|
|
|
assert.Check(t, role.ManagedPolicyArns[0] == ecsTaskExecutionPolicy)
|
|
|
|
assert.Check(t, role.ManagedPolicyArns[1] == ecrReadOnlyPolicy)
|
2020-06-08 11:28:15 +02:00
|
|
|
// We expect an extra policy has been created for x-aws-pull_credentials
|
|
|
|
assert.Check(t, len(role.Policies) == 1)
|
|
|
|
policy := role.Policies[0].PolicyDocument.(*PolicyDocument)
|
|
|
|
expected := []string{"secretsmanager:GetSecretValue", "ssm:GetParameters", "kms:Decrypt"}
|
|
|
|
assert.DeepEqual(t, expected, policy.Statement[0].Action)
|
|
|
|
assert.DeepEqual(t, []string{"secret"}, policy.Statement[0].Resource)
|
|
|
|
}
|
|
|
|
|
2020-06-08 09:16:58 +02:00
|
|
|
func TestMapNetworksToSecurityGroups(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-06-08 09:16:58 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: hello_world
|
2020-06-17 14:48:42 +02:00
|
|
|
networks:
|
2020-07-15 07:50:40 +02:00
|
|
|
- front-tier
|
|
|
|
- back-tier
|
2020-06-17 14:48:42 +02:00
|
|
|
|
2020-06-08 09:16:58 +02:00
|
|
|
networks:
|
|
|
|
front-tier:
|
|
|
|
name: public
|
|
|
|
back-tier:
|
|
|
|
internal: true
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-09-24 16:11:08 +02:00
|
|
|
assert.Check(t, template.Resources["FronttierNetwork"] != nil)
|
|
|
|
assert.Check(t, template.Resources["BacktierNetwork"] != nil)
|
|
|
|
assert.Check(t, template.Resources["BacktierNetworkIngress"] != nil)
|
|
|
|
i := template.Resources["FronttierNetworkIngress"]
|
2020-08-18 16:56:42 +02:00
|
|
|
assert.Check(t, i != nil)
|
|
|
|
ingress := *i.(*ec2.SecurityGroupIngress)
|
2020-09-24 16:11:08 +02:00
|
|
|
assert.Check(t, ingress.SourceSecurityGroupId == cloudformation.Ref("FronttierNetwork"))
|
2020-06-08 09:16:58 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-06-08 15:34:33 +02:00
|
|
|
func TestLoadBalancerTypeApplication(t *testing.T) {
|
2020-09-07 10:52:34 +02:00
|
|
|
cases := []string{
|
|
|
|
`services:
|
2020-06-08 15:34:33 +02:00
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
ports:
|
|
|
|
- 80:80
|
2020-09-07 10:52:34 +02:00
|
|
|
`,
|
|
|
|
`services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
ports:
|
|
|
|
- target: 8080
|
|
|
|
x-aws-protocol: http
|
|
|
|
`,
|
|
|
|
}
|
|
|
|
for _, y := range cases {
|
2020-10-12 16:21:48 +02:00
|
|
|
template := convertYaml(t, y, useDefaultVPC)
|
2020-09-24 16:11:08 +02:00
|
|
|
lb := template.Resources["LoadBalancer"]
|
2020-09-07 10:52:34 +02:00
|
|
|
assert.Check(t, lb != nil)
|
|
|
|
loadBalancer := *lb.(*elasticloadbalancingv2.LoadBalancer)
|
|
|
|
assert.Check(t, len(loadBalancer.Name) <= 32)
|
|
|
|
assert.Check(t, loadBalancer.Type == elbv2.LoadBalancerTypeEnumApplication)
|
|
|
|
assert.Check(t, len(loadBalancer.SecurityGroups) > 0)
|
|
|
|
}
|
2020-06-08 15:34:33 +02:00
|
|
|
}
|
|
|
|
|
2020-07-15 18:02:57 +02:00
|
|
|
func TestNoLoadBalancerIfNoPortExposed(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-07-15 18:02:57 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
foo:
|
|
|
|
image: bar
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-07-15 18:02:57 +02:00
|
|
|
for _, r := range template.Resources {
|
|
|
|
assert.Check(t, r.AWSCloudFormationType() != "AWS::ElasticLoadBalancingV2::TargetGroup")
|
|
|
|
assert.Check(t, r.AWSCloudFormationType() != "AWS::ElasticLoadBalancingV2::Listener")
|
2020-08-18 11:38:23 +02:00
|
|
|
assert.Check(t, r.AWSCloudFormationType() != "AWS::ElasticLoadBalancingV2::PortPublisher")
|
2020-07-15 18:02:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-10 09:35:32 +02:00
|
|
|
func TestServiceReplicas(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-07-10 09:35:32 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
deploy:
|
|
|
|
replicas: 10
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-08-18 16:56:42 +02:00
|
|
|
s := template.Resources["TestService"]
|
2020-07-10 09:35:32 +02:00
|
|
|
assert.Check(t, s != nil)
|
2020-08-18 16:56:42 +02:00
|
|
|
service := *s.(*ecs.Service)
|
|
|
|
assert.Check(t, service.DesiredCount == 10)
|
2020-07-10 09:35:32 +02:00
|
|
|
}
|
|
|
|
|
2020-07-23 14:37:05 +02:00
|
|
|
func TestTaskSizeConvert(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-09-22 12:15:55 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-09-22 12:15:55 +02:00
|
|
|
def := template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition)
|
|
|
|
assert.Equal(t, def.Cpu, "256")
|
|
|
|
assert.Equal(t, def.Memory, "512")
|
|
|
|
|
|
|
|
template = convertYaml(t, `
|
2020-07-23 14:37:05 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
deploy:
|
|
|
|
resources:
|
|
|
|
limits:
|
|
|
|
cpus: '0.5'
|
|
|
|
memory: 2048M
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-09-22 12:15:55 +02:00
|
|
|
def = template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition)
|
2020-07-23 14:37:05 +02:00
|
|
|
assert.Equal(t, def.Cpu, "512")
|
|
|
|
assert.Equal(t, def.Memory, "2048")
|
|
|
|
|
2020-08-18 16:56:42 +02:00
|
|
|
template = convertYaml(t, `
|
2020-07-23 14:37:05 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
deploy:
|
|
|
|
resources:
|
|
|
|
limits:
|
|
|
|
cpus: '4'
|
|
|
|
memory: 8192M
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-07-23 14:37:05 +02:00
|
|
|
def = template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition)
|
|
|
|
assert.Equal(t, def.Cpu, "4096")
|
|
|
|
assert.Equal(t, def.Memory, "8192")
|
2020-09-22 12:15:55 +02:00
|
|
|
|
|
|
|
template = convertYaml(t, `
|
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
deploy:
|
|
|
|
resources:
|
|
|
|
limits:
|
|
|
|
cpus: '4'
|
|
|
|
memory: 792Mb
|
|
|
|
reservations:
|
|
|
|
generic_resources:
|
|
|
|
- discrete_resource_spec:
|
|
|
|
kind: gpus
|
|
|
|
value: 2
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC, useGPU)
|
2020-09-22 12:15:55 +02:00
|
|
|
def = template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition)
|
|
|
|
assert.Equal(t, def.Cpu, "4000")
|
|
|
|
assert.Equal(t, def.Memory, "792")
|
2020-09-23 10:04:19 +02:00
|
|
|
|
|
|
|
template = convertYaml(t, `
|
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
deploy:
|
|
|
|
resources:
|
|
|
|
reservations:
|
|
|
|
generic_resources:
|
|
|
|
- discrete_resource_spec:
|
|
|
|
kind: gpus
|
|
|
|
value: 2
|
2020-11-16 14:09:12 +01:00
|
|
|
`, useDefaultVPC, useGPU)
|
|
|
|
def = template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition)
|
|
|
|
assert.Equal(t, def.Cpu, "")
|
|
|
|
assert.Equal(t, def.Memory, "")
|
|
|
|
|
|
|
|
template = convertYaml(t, `
|
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
deploy:
|
|
|
|
resources:
|
|
|
|
reservations:
|
|
|
|
devices:
|
|
|
|
- capabilities: [gpu]
|
|
|
|
count: 2
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC, useGPU)
|
2020-09-23 10:04:19 +02:00
|
|
|
def = template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition)
|
|
|
|
assert.Equal(t, def.Cpu, "")
|
|
|
|
assert.Equal(t, def.Memory, "")
|
2020-07-23 14:37:05 +02:00
|
|
|
}
|
|
|
|
|
2020-06-08 15:34:33 +02:00
|
|
|
func TestLoadBalancerTypeNetwork(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-06-08 15:34:33 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
ports:
|
|
|
|
- 80:80
|
|
|
|
- 88:88
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-09-24 16:11:08 +02:00
|
|
|
lb := template.Resources["LoadBalancer"]
|
2020-06-08 15:34:33 +02:00
|
|
|
assert.Check(t, lb != nil)
|
2020-08-18 16:56:42 +02:00
|
|
|
loadBalancer := *lb.(*elasticloadbalancingv2.LoadBalancer)
|
|
|
|
assert.Check(t, loadBalancer.Type == elbv2.LoadBalancerTypeEnumNetwork)
|
2020-06-08 15:34:33 +02:00
|
|
|
}
|
|
|
|
|
2020-10-09 08:18:39 +02:00
|
|
|
func TestUseExternalNetwork(t *testing.T) {
|
2020-10-12 16:21:48 +02:00
|
|
|
template := convertYaml(t, `
|
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
networks:
|
|
|
|
default:
|
|
|
|
external: true
|
|
|
|
name: sg-123abc
|
|
|
|
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
|
|
|
m.SecurityGroupExists(gomock.Any(), "sg-123abc").Return(true, nil)
|
|
|
|
})
|
|
|
|
assert.Check(t, template.Resources["DefaultNetwork"] == nil)
|
|
|
|
assert.Check(t, template.Resources["DefaultNetworkIngress"] == nil)
|
|
|
|
s := template.Resources["TestService"].(*ecs.Service)
|
2021-04-13 15:35:10 +02:00
|
|
|
assert.Check(t, s != nil) //nolint:staticcheck
|
2020-10-12 16:21:48 +02:00
|
|
|
assert.Check(t, s.NetworkConfiguration.AwsvpcConfiguration.SecurityGroups[0] == "sg-123abc") //nolint:staticcheck
|
|
|
|
}
|
|
|
|
|
2020-10-09 08:18:39 +02:00
|
|
|
func TestUseExternalVolume(t *testing.T) {
|
2020-10-14 11:04:50 +02:00
|
|
|
template := convertYaml(t, `
|
2020-10-09 08:18:39 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
volumes:
|
|
|
|
db-data:
|
|
|
|
external: true
|
|
|
|
name: fs-123abc
|
|
|
|
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
2020-10-19 09:48:23 +02:00
|
|
|
m.ResolveFileSystem(gomock.Any(), "fs-123abc").Return(existingAWSResource{id: "fs-123abc"}, nil)
|
2020-10-09 08:18:39 +02:00
|
|
|
})
|
2020-10-14 11:04:50 +02:00
|
|
|
s := template.Resources["DbdataNFSMountTargetOnSubnet1"].(*efs.MountTarget)
|
2021-04-13 15:35:10 +02:00
|
|
|
assert.Check(t, s != nil) //nolint:staticcheck
|
2020-10-14 11:04:50 +02:00
|
|
|
assert.Equal(t, s.FileSystemId, "fs-123abc") //nolint:staticcheck
|
|
|
|
|
|
|
|
s = template.Resources["DbdataNFSMountTargetOnSubnet2"].(*efs.MountTarget)
|
2021-04-13 15:35:10 +02:00
|
|
|
assert.Check(t, s != nil) //nolint:staticcheck
|
2020-10-14 11:04:50 +02:00
|
|
|
assert.Equal(t, s.FileSystemId, "fs-123abc") //nolint:staticcheck
|
2020-10-09 08:18:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCreateVolume(t *testing.T) {
|
2020-10-14 11:04:50 +02:00
|
|
|
template := convertYaml(t, `
|
2020-10-09 08:18:39 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
volumes:
|
2020-10-14 11:04:50 +02:00
|
|
|
db-data:
|
|
|
|
driver_opts:
|
|
|
|
backup_policy: ENABLED
|
|
|
|
lifecycle_policy: AFTER_30_DAYS
|
|
|
|
performance_mode: maxIO
|
|
|
|
throughput_mode: provisioned
|
|
|
|
provisioned_throughput: 1024
|
2020-10-09 08:18:39 +02:00
|
|
|
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
2020-10-19 17:35:40 +02:00
|
|
|
m.ListFileSystems(gomock.Any(), map[string]string{
|
2021-06-14 16:26:14 +02:00
|
|
|
api.ProjectLabel: t.Name(),
|
|
|
|
api.VolumeLabel: "db-data",
|
2020-10-19 09:48:23 +02:00
|
|
|
}).Return(nil, nil)
|
2020-10-09 08:18:39 +02:00
|
|
|
})
|
2020-10-14 11:04:50 +02:00
|
|
|
n := volumeResourceName("db-data")
|
|
|
|
f := template.Resources[n].(*efs.FileSystem)
|
2021-04-13 15:35:10 +02:00
|
|
|
assert.Check(t, f != nil) //nolint:staticcheck
|
2020-10-14 11:04:50 +02:00
|
|
|
assert.Equal(t, f.BackupPolicy.Status, "ENABLED") //nolint:staticcheck
|
|
|
|
assert.Equal(t, f.LifecyclePolicies[0].TransitionToIA, "AFTER_30_DAYS") //nolint:staticcheck
|
|
|
|
assert.Equal(t, f.PerformanceMode, "maxIO") //nolint:staticcheck
|
|
|
|
assert.Equal(t, f.ThroughputMode, "provisioned") //nolint:staticcheck
|
|
|
|
assert.Equal(t, f.ProvisionedThroughputInMibps, float64(1024)) //nolint:staticcheck
|
|
|
|
|
|
|
|
s := template.Resources["DbdataNFSMountTargetOnSubnet1"].(*efs.MountTarget)
|
2021-04-13 15:35:10 +02:00
|
|
|
assert.Check(t, s != nil) //nolint:staticcheck
|
2020-10-14 11:04:50 +02:00
|
|
|
assert.Equal(t, s.FileSystemId, cloudformation.Ref(n)) //nolint:staticcheck
|
2020-10-09 08:18:39 +02:00
|
|
|
}
|
|
|
|
|
2020-10-19 09:48:23 +02:00
|
|
|
func TestCreateAccessPoint(t *testing.T) {
|
|
|
|
template := convertYaml(t, `
|
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
volumes:
|
|
|
|
db-data:
|
|
|
|
driver_opts:
|
|
|
|
uid: 1002
|
|
|
|
gid: 1002
|
|
|
|
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
2020-10-19 17:35:40 +02:00
|
|
|
m.ListFileSystems(gomock.Any(), gomock.Any()).Return(nil, nil)
|
2020-10-19 09:48:23 +02:00
|
|
|
})
|
|
|
|
a := template.Resources["DbdataAccessPoint"].(*efs.AccessPoint)
|
2021-04-13 15:35:10 +02:00
|
|
|
assert.Check(t, a != nil) //nolint:staticcheck
|
2020-10-19 09:48:23 +02:00
|
|
|
assert.Equal(t, a.PosixUser.Uid, "1002") //nolint:staticcheck
|
|
|
|
assert.Equal(t, a.PosixUser.Gid, "1002") //nolint:staticcheck
|
|
|
|
}
|
|
|
|
|
2020-10-09 08:18:39 +02:00
|
|
|
func TestReusePreviousVolume(t *testing.T) {
|
2020-10-14 11:04:50 +02:00
|
|
|
template := convertYaml(t, `
|
2020-10-09 08:18:39 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
volumes:
|
|
|
|
db-data: {}
|
|
|
|
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
2020-10-19 17:35:40 +02:00
|
|
|
m.ListFileSystems(gomock.Any(), map[string]string{
|
2021-06-14 16:26:14 +02:00
|
|
|
api.ProjectLabel: t.Name(),
|
|
|
|
api.VolumeLabel: "db-data",
|
2020-10-19 17:35:40 +02:00
|
|
|
}).Return([]awsResource{
|
|
|
|
existingAWSResource{
|
|
|
|
id: "fs-123abc",
|
|
|
|
},
|
|
|
|
}, nil)
|
2020-10-09 08:18:39 +02:00
|
|
|
})
|
2020-10-14 11:04:50 +02:00
|
|
|
s := template.Resources["DbdataNFSMountTargetOnSubnet1"].(*efs.MountTarget)
|
2021-04-13 15:35:10 +02:00
|
|
|
assert.Check(t, s != nil) //nolint:staticcheck
|
2020-10-14 11:04:50 +02:00
|
|
|
assert.Equal(t, s.FileSystemId, "fs-123abc") //nolint:staticcheck
|
2020-10-09 08:18:39 +02:00
|
|
|
}
|
|
|
|
|
2020-06-30 17:15:52 +02:00
|
|
|
func TestServiceMapping(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-06-30 17:15:52 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: "image"
|
|
|
|
command: "command"
|
|
|
|
entrypoint: "entrypoint"
|
|
|
|
environment:
|
|
|
|
- "FOO=BAR"
|
|
|
|
cap_add:
|
|
|
|
- SYS_PTRACE
|
|
|
|
cap_drop:
|
|
|
|
- SYSLOG
|
|
|
|
init: true
|
|
|
|
user: "user"
|
|
|
|
working_dir: "working_dir"
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-06-30 17:15:52 +02:00
|
|
|
def := template.Resources["TestTaskDefinition"].(*ecs.TaskDefinition)
|
2020-09-28 13:36:12 +02:00
|
|
|
container := getMainContainer(def, t)
|
2020-07-08 16:07:13 +02:00
|
|
|
assert.Equal(t, container.Image, "image")
|
2020-06-30 17:15:52 +02:00
|
|
|
assert.Equal(t, container.Command[0], "command")
|
|
|
|
assert.Equal(t, container.EntryPoint[0], "entrypoint")
|
|
|
|
assert.Equal(t, get(container.Environment, "FOO"), "BAR")
|
|
|
|
assert.Check(t, container.LinuxParameters.InitProcessEnabled)
|
|
|
|
assert.Equal(t, container.LinuxParameters.Capabilities.Add[0], "SYS_PTRACE")
|
|
|
|
assert.Equal(t, container.LinuxParameters.Capabilities.Drop[0], "SYSLOG")
|
|
|
|
assert.Equal(t, container.User, "user")
|
|
|
|
assert.Equal(t, container.WorkingDirectory, "working_dir")
|
|
|
|
}
|
|
|
|
|
|
|
|
func get(l []ecs.TaskDefinition_KeyValuePair, name string) string {
|
|
|
|
for _, e := range l {
|
|
|
|
if e.Name == name {
|
|
|
|
return e.Value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2020-06-30 15:52:04 +02:00
|
|
|
func TestResourcesHaveProjectTagSet(t *testing.T) {
|
2020-08-18 16:56:42 +02:00
|
|
|
template := convertYaml(t, `
|
2020-06-30 15:52:04 +02:00
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
ports:
|
|
|
|
- 80:80
|
|
|
|
- 88:88
|
2020-10-12 16:21:48 +02:00
|
|
|
`, useDefaultVPC)
|
2020-06-30 15:52:04 +02:00
|
|
|
for _, r := range template.Resources {
|
|
|
|
tags := reflect.Indirect(reflect.ValueOf(r)).FieldByName("Tags")
|
|
|
|
if !tags.IsValid() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for i := 0; i < tags.Len(); i++ {
|
|
|
|
k := tags.Index(i).FieldByName("Key").String()
|
|
|
|
v := tags.Index(i).FieldByName("Value").String()
|
2021-06-14 16:26:14 +02:00
|
|
|
if k == api.ProjectLabel {
|
2020-10-12 16:21:48 +02:00
|
|
|
assert.Equal(t, v, t.Name())
|
2020-06-30 15:52:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-16 10:48:19 +02:00
|
|
|
func TestTemplateMetadata(t *testing.T) {
|
|
|
|
template := convertYaml(t, `
|
|
|
|
x-aws-cluster: "arn:aws:ecs:region:account:cluster/name"
|
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
2020-10-19 09:48:23 +02:00
|
|
|
m.ResolveCluster(gomock.Any(), "arn:aws:ecs:region:account:cluster/name").Return(existingAWSResource{
|
|
|
|
arn: "arn:aws:ecs:region:account:cluster/name",
|
|
|
|
id: "name",
|
|
|
|
}, nil)
|
2020-10-16 10:48:19 +02:00
|
|
|
})
|
|
|
|
assert.Equal(t, template.Metadata["Cluster"], "arn:aws:ecs:region:account:cluster/name")
|
|
|
|
}
|
|
|
|
|
2020-12-16 10:37:16 +01:00
|
|
|
func TestARNUsedAsVpcID(t *testing.T) {
|
|
|
|
convertYaml(t, `
|
|
|
|
x-aws-vpc: "arn:aws:ec2:us-west-1:EXAMPLE:vpc/vpc-1234acbd"
|
|
|
|
services:
|
|
|
|
test:
|
|
|
|
image: nginx
|
|
|
|
`, func(m *MockAPIMockRecorder) {
|
|
|
|
m.CheckVPC(gomock.Any(), "vpc-1234acbd").Return(nil)
|
|
|
|
m.GetSubNets(gomock.Any(), "vpc-1234acbd").Return([]awsResource{
|
|
|
|
existingAWSResource{id: "subnet1"},
|
|
|
|
existingAWSResource{id: "subnet2"},
|
|
|
|
}, nil)
|
|
|
|
m.IsPublicSubnet(gomock.Any(), "subnet1").Return(true, nil)
|
|
|
|
m.IsPublicSubnet(gomock.Any(), "subnet2").Return(true, nil)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-10-12 16:21:48 +02:00
|
|
|
func convertYaml(t *testing.T, yaml string, fn ...func(m *MockAPIMockRecorder)) *cloudformation.Template {
|
|
|
|
project := loadConfig(t, yaml)
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
2020-05-18 10:53:07 +02:00
|
|
|
|
2020-10-12 16:21:48 +02:00
|
|
|
m := NewMockAPI(ctrl)
|
|
|
|
for _, f := range fn {
|
|
|
|
f(m.EXPECT())
|
2020-05-18 10:53:07 +02:00
|
|
|
}
|
2020-06-08 09:16:58 +02:00
|
|
|
|
2020-10-12 16:21:48 +02:00
|
|
|
backend := &ecsAPIService{
|
|
|
|
aws: m,
|
|
|
|
}
|
|
|
|
template, err := backend.convert(context.TODO(), project)
|
2020-07-23 20:17:41 +02:00
|
|
|
assert.NilError(t, err)
|
|
|
|
return template
|
|
|
|
}
|
|
|
|
|
2020-08-18 16:56:42 +02:00
|
|
|
func loadConfig(t *testing.T, yaml string) *types.Project {
|
2020-06-08 09:16:58 +02:00
|
|
|
dict, err := loader.ParseYAML([]byte(yaml))
|
|
|
|
assert.NilError(t, err)
|
|
|
|
model, err := loader.Load(types.ConfigDetails{
|
|
|
|
ConfigFiles: []types.ConfigFile{
|
|
|
|
{Config: dict},
|
|
|
|
},
|
2020-06-17 14:48:42 +02:00
|
|
|
}, func(options *loader.Options) {
|
2020-10-12 16:21:48 +02:00
|
|
|
options.Name = t.Name()
|
2020-06-08 09:16:58 +02:00
|
|
|
})
|
|
|
|
assert.NilError(t, err)
|
2020-07-23 20:17:41 +02:00
|
|
|
return model
|
2020-06-08 09:16:58 +02:00
|
|
|
}
|
2020-09-28 13:36:12 +02:00
|
|
|
|
|
|
|
func getMainContainer(def *ecs.TaskDefinition, t *testing.T) ecs.TaskDefinition_ContainerDefinition {
|
|
|
|
for _, c := range def.ContainerDefinitions {
|
|
|
|
if c.Essential {
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t.Fail()
|
|
|
|
return def.ContainerDefinitions[0]
|
|
|
|
}
|
2020-10-12 16:21:48 +02:00
|
|
|
|
|
|
|
func useDefaultVPC(m *MockAPIMockRecorder) {
|
|
|
|
m.GetDefaultVPC(gomock.Any()).Return("vpc-123", nil)
|
2020-10-19 09:48:23 +02:00
|
|
|
m.GetSubNets(gomock.Any(), "vpc-123").Return([]awsResource{
|
|
|
|
existingAWSResource{id: "subnet1"},
|
|
|
|
existingAWSResource{id: "subnet2"},
|
|
|
|
}, nil)
|
2020-12-15 12:33:53 +01:00
|
|
|
m.IsPublicSubnet(gomock.Any(), "subnet1").Return(true, nil)
|
|
|
|
m.IsPublicSubnet(gomock.Any(), "subnet2").Return(true, nil)
|
2020-10-12 16:21:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func useGPU(m *MockAPIMockRecorder) {
|
|
|
|
m.GetParameter(gomock.Any(), gomock.Any()).Return("", nil)
|
|
|
|
}
|