Don't create a LoadBalancer if compose app has no port exposed

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2020-07-15 18:02:57 +02:00
parent b2a9019700
commit dbbd24d270
No known key found for this signature in database
GPG Key ID: 9858809D6F8F6E7E
6 changed files with 117 additions and 313 deletions

View File

@ -142,14 +142,16 @@ func (b Backend) Convert(project *types.Project) (*cloudformation.Template, erro
protocol = elbv2.ProtocolEnumHttp protocol = elbv2.ProtocolEnumHttp
} }
} }
targetGroupName := createTargetGroup(project, service, port, template, protocol) if loadBalancerARN != "" {
listenerName := createListener(service, port, template, targetGroupName, loadBalancerARN, protocol) targetGroupName := createTargetGroup(project, service, port, template, protocol)
dependsOn = append(dependsOn, listenerName) listenerName := createListener(service, port, template, targetGroupName, loadBalancerARN, protocol)
serviceLB = append(serviceLB, ecs.Service_LoadBalancer{ dependsOn = append(dependsOn, listenerName)
ContainerName: service.Name, serviceLB = append(serviceLB, ecs.Service_LoadBalancer{
ContainerPort: int(port.Target), ContainerName: service.Name,
TargetGroupArn: cloudformation.Ref(targetGroupName), ContainerPort: int(port.Target),
}) TargetGroupArn: cloudformation.Ref(targetGroupName),
})
}
} }
} }
@ -218,6 +220,15 @@ func getLoadBalancerSecurityGroups(project *types.Project, template *cloudformat
} }
func createLoadBalancer(project *types.Project, template *cloudformation.Template) string { func createLoadBalancer(project *types.Project, template *cloudformation.Template) string {
ports := 0
for _, service := range project.Services {
ports += len(service.Ports)
}
if ports == 0 {
// Project do not expose any port (batch jobs?)
// So no need to create a LoadBalancer
return ""
}
// load balancer names are limited to 32 characters total // load balancer names are limited to 32 characters total
loadBalancerName := fmt.Sprintf("%.32s", fmt.Sprintf("%sLoadBalancer", strings.Title(project.Name))) loadBalancerName := fmt.Sprintf("%.32s", fmt.Sprintf("%sLoadBalancer", strings.Title(project.Name)))

View File

@ -26,13 +26,6 @@ func TestSimpleConvert(t *testing.T) {
golden.Assert(t, result, expected) golden.Assert(t, result, expected)
} }
func TestSimpleWithOverrides(t *testing.T) {
project := load(t, "testdata/input/simple-single-service.yaml", "testdata/input/simple-single-service-with-overrides.yaml")
result := convertResultAsString(t, project, "TestCluster")
expected := "simple/simple-cloudformation-with-overrides-conversion.golden"
golden.Assert(t, result, expected)
}
func TestRolePolicy(t *testing.T) { func TestRolePolicy(t *testing.T) {
template := convertYaml(t, "test", ` template := convertYaml(t, "test", `
version: "3" version: "3"
@ -94,6 +87,22 @@ services:
assert.Check(t, len(lb.SecurityGroups) > 0) assert.Check(t, len(lb.SecurityGroups) > 0)
} }
func TestNoLoadBalancerIfNoPortExposed(t *testing.T) {
template := convertYaml(t, "test", `
version: "3"
services:
test:
image: nginx
foo:
image: bar
`)
for _, r := range template.Resources {
assert.Check(t, r.AWSCloudFormationType() != "AWS::ElasticLoadBalancingV2::TargetGroup")
assert.Check(t, r.AWSCloudFormationType() != "AWS::ElasticLoadBalancingV2::Listener")
assert.Check(t, r.AWSCloudFormationType() != "AWS::ElasticLoadBalancingV2::LoadBalancer")
}
}
func TestServiceReplicas(t *testing.T) { func TestServiceReplicas(t *testing.T) {
template := convertYaml(t, "test", ` template := convertYaml(t, "test", `
version: "3" version: "3"

View File

@ -1,4 +0,0 @@
version: "3"
services:
simple:
image: haproxy

View File

@ -2,3 +2,5 @@ version: "3"
services: services:
simple: simple:
image: nginx image: nginx
ports:
- "80:80"

View File

@ -71,6 +71,9 @@
"Type": "AWS::Logs::LogGroup" "Type": "AWS::Logs::LogGroup"
}, },
"SimpleService": { "SimpleService": {
"DependsOn": [
"SimpleTCP80Listener"
],
"Properties": { "Properties": {
"Cluster": { "Cluster": {
"Fn::If": [ "Fn::If": [
@ -85,6 +88,15 @@
}, },
"DesiredCount": 1, "DesiredCount": 1,
"LaunchType": "FARGATE", "LaunchType": "FARGATE",
"LoadBalancers": [
{
"ContainerName": "simple",
"ContainerPort": 80,
"TargetGroupArn": {
"Ref": "SimpleTCP80TargetGroup"
}
}
],
"NetworkConfiguration": { "NetworkConfiguration": {
"AwsvpcConfiguration": { "AwsvpcConfiguration": {
"AssignPublicIp": "ENABLED", "AssignPublicIp": "ENABLED",
@ -152,6 +164,56 @@
}, },
"Type": "AWS::ServiceDiscovery::Service" "Type": "AWS::ServiceDiscovery::Service"
}, },
"SimpleTCP80Listener": {
"Properties": {
"DefaultActions": [
{
"ForwardConfig": {
"TargetGroups": [
{
"TargetGroupArn": {
"Ref": "SimpleTCP80TargetGroup"
}
}
]
},
"Type": "forward"
}
],
"LoadBalancerArn": {
"Fn::If": [
"CreateLoadBalancer",
{
"Ref": "TestSimpleConvertLoadBalancer"
},
{
"Ref": "ParameterLoadBalancerARN"
}
]
},
"Port": 80,
"Protocol": "HTTP"
},
"Type": "AWS::ElasticLoadBalancingV2::Listener"
},
"SimpleTCP80TargetGroup": {
"Properties": {
"Name": "SimpleTCP80TargetGroup",
"Port": 80,
"Protocol": "HTTP",
"Tags": [
{
"Key": "com.docker.compose.project",
"Value": "TestSimpleConvert"
}
],
"TargetType": "ip",
"VpcId": {
"Ref": "ParameterVPCId"
}
},
"Type": "AWS::ElasticLoadBalancingV2::TargetGroup"
},
"SimpleTaskDefinition": { "SimpleTaskDefinition": {
"Properties": { "Properties": {
"ContainerDefinitions": [ "ContainerDefinitions": [
@ -188,7 +250,14 @@
"awslogs-stream-prefix": "TestSimpleConvert" "awslogs-stream-prefix": "TestSimpleConvert"
} }
}, },
"Name": "simple" "Name": "simple",
"PortMappings": [
{
"ContainerPort": 80,
"HostPort": 80,
"Protocol": "tcp"
}
]
} }
], ],
"Cpu": "256", "Cpu": "256",
@ -231,6 +300,15 @@
"Properties": { "Properties": {
"GroupDescription": "TestSimpleConvert default Security Group", "GroupDescription": "TestSimpleConvert default Security Group",
"GroupName": "TestSimpleConvertDefaultNetwork", "GroupName": "TestSimpleConvertDefaultNetwork",
"SecurityGroupIngress": [
{
"CidrIp": "0.0.0.0/0",
"Description": "simple:80/tcp",
"FromPort": 80,
"IpProtocol": "TCP",
"ToPort": 80
}
],
"Tags": [ "Tags": [
{ {
"Key": "com.docker.compose.project", "Key": "com.docker.compose.project",

View File

@ -1,292 +0,0 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Conditions": {
"CreateCluster": {
"Fn::Equals": [
"",
{
"Ref": "ParameterClusterName"
}
]
},
"CreateLoadBalancer": {
"Fn::Equals": [
"",
{
"Ref": "ParameterLoadBalancerARN"
}
]
}
},
"Parameters": {
"ParameterClusterName": {
"Description": "Name of the ECS cluster to deploy to (optional)",
"Type": "String"
},
"ParameterLoadBalancerARN": {
"Description": "Name of the LoadBalancer to connect to (optional)",
"Type": "String"
},
"ParameterSubnet1Id": {
"Description": "SubnetId, for Availability Zone 1 in the region in your VPC",
"Type": "AWS::EC2::Subnet::Id"
},
"ParameterSubnet2Id": {
"Description": "SubnetId, for Availability Zone 2 in the region in your VPC",
"Type": "AWS::EC2::Subnet::Id"
},
"ParameterVPCId": {
"Description": "ID of the VPC",
"Type": "AWS::EC2::VPC::Id"
}
},
"Resources": {
"CloudMap": {
"Properties": {
"Description": "Service Map for Docker Compose project TestSimpleWithOverrides",
"Name": "TestSimpleWithOverrides.local",
"Vpc": {
"Ref": "ParameterVPCId"
}
},
"Type": "AWS::ServiceDiscovery::PrivateDnsNamespace"
},
"Cluster": {
"Condition": "CreateCluster",
"Properties": {
"ClusterName": "TestSimpleWithOverrides",
"Tags": [
{
"Key": "com.docker.compose.project",
"Value": "TestSimpleWithOverrides"
}
]
},
"Type": "AWS::ECS::Cluster"
},
"LogGroup": {
"Properties": {
"LogGroupName": "/docker-compose/TestSimpleWithOverrides"
},
"Type": "AWS::Logs::LogGroup"
},
"SimpleService": {
"Properties": {
"Cluster": {
"Fn::If": [
"CreateCluster",
{
"Ref": "Cluster"
},
{
"Ref": "ParameterClusterName"
}
]
},
"DesiredCount": 1,
"LaunchType": "FARGATE",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"AssignPublicIp": "ENABLED",
"SecurityGroups": [
{
"Ref": "TestSimpleWithOverridesDefaultNetwork"
}
],
"Subnets": [
{
"Ref": "ParameterSubnet1Id"
},
{
"Ref": "ParameterSubnet2Id"
}
]
}
},
"SchedulingStrategy": "REPLICA",
"ServiceRegistries": [
{
"RegistryArn": {
"Fn::GetAtt": [
"SimpleServiceDiscoveryEntry",
"Arn"
]
}
}
],
"Tags": [
{
"Key": "com.docker.compose.project",
"Value": "TestSimpleWithOverrides"
},
{
"Key": "com.docker.compose.service",
"Value": "simple"
}
],
"TaskDefinition": {
"Ref": "SimpleTaskDefinition"
}
},
"Type": "AWS::ECS::Service"
},
"SimpleServiceDiscoveryEntry": {
"Properties": {
"Description": "\"simple\" service discovery entry in Cloud Map",
"DnsConfig": {
"DnsRecords": [
{
"TTL": 60,
"Type": "A"
}
],
"RoutingPolicy": "MULTIVALUE"
},
"HealthCheckCustomConfig": {
"FailureThreshold": 1
},
"Name": "simple",
"NamespaceId": {
"Ref": "CloudMap"
}
},
"Type": "AWS::ServiceDiscovery::Service"
},
"SimpleTaskDefinition": {
"Properties": {
"ContainerDefinitions": [
{
"Environment": [
{
"Name": "LOCALDOMAIN",
"Value": {
"Fn::Join": [
"",
[
{
"Ref": "AWS::Region"
},
".compute.internal",
" TestSimpleWithOverrides.local"
]
]
}
}
],
"Essential": true,
"Image": "haproxy",
"LinuxParameters": {},
"LogConfiguration": {
"LogDriver": "awslogs",
"Options": {
"awslogs-group": {
"Ref": "LogGroup"
},
"awslogs-region": {
"Ref": "AWS::Region"
},
"awslogs-stream-prefix": "TestSimpleWithOverrides"
}
},
"Name": "simple"
}
],
"Cpu": "256",
"ExecutionRoleArn": {
"Ref": "SimpleTaskExecutionRole"
},
"Family": "TestSimpleWithOverrides-simple",
"Memory": "512",
"NetworkMode": "awsvpc",
"RequiresCompatibilities": [
"FARGATE"
]
},
"Type": "AWS::ECS::TaskDefinition"
},
"SimpleTaskExecutionRole": {
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": [
"sts:AssumeRole"
],
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
]
},
"Type": "AWS::IAM::Role"
},
"TestSimpleWithOverridesDefaultNetwork": {
"Properties": {
"GroupDescription": "TestSimpleWithOverrides default Security Group",
"GroupName": "TestSimpleWithOverridesDefaultNetwork",
"Tags": [
{
"Key": "com.docker.compose.project",
"Value": "TestSimpleWithOverrides"
},
{
"Key": "com.docker.compose.network",
"Value": "default"
}
],
"VpcId": {
"Ref": "ParameterVPCId"
}
},
"Type": "AWS::EC2::SecurityGroup"
},
"TestSimpleWithOverridesDefaultNetworkIngress": {
"Properties": {
"Description": "Allow communication within network default",
"GroupId": {
"Ref": "TestSimpleWithOverridesDefaultNetwork"
},
"IpProtocol": "-1",
"SourceSecurityGroupId": {
"Ref": "TestSimpleWithOverridesDefaultNetwork"
}
},
"Type": "AWS::EC2::SecurityGroupIngress"
},
"TestSimpleWithOverridesLoadBalan": {
"Condition": "CreateLoadBalancer",
"Properties": {
"Name": "TestSimpleWithOverridesLoadBalan",
"Scheme": "internet-facing",
"SecurityGroups": [
{
"Ref": "TestSimpleWithOverridesDefaultNetwork"
}
],
"Subnets": [
{
"Ref": "ParameterSubnet1Id"
},
{
"Ref": "ParameterSubnet2Id"
}
],
"Tags": [
{
"Key": "com.docker.compose.project",
"Value": "TestSimpleWithOverrides"
}
],
"Type": "application"
},
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer"
}
}
}