Browse Source

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

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 5 years ago
parent
commit
dbbd24d270

+ 19 - 8
ecs/pkg/amazon/backend/cloudformation.go

@@ -142,14 +142,16 @@ func (b Backend) Convert(project *types.Project) (*cloudformation.Template, erro
 						protocol = elbv2.ProtocolEnumHttp
 					}
 				}
-				targetGroupName := createTargetGroup(project, service, port, template, protocol)
-				listenerName := createListener(service, port, template, targetGroupName, loadBalancerARN, protocol)
-				dependsOn = append(dependsOn, listenerName)
-				serviceLB = append(serviceLB, ecs.Service_LoadBalancer{
-					ContainerName:  service.Name,
-					ContainerPort:  int(port.Target),
-					TargetGroupArn: cloudformation.Ref(targetGroupName),
-				})
+				if loadBalancerARN != "" {
+					targetGroupName := createTargetGroup(project, service, port, template, protocol)
+					listenerName := createListener(service, port, template, targetGroupName, loadBalancerARN, protocol)
+					dependsOn = append(dependsOn, listenerName)
+					serviceLB = append(serviceLB, ecs.Service_LoadBalancer{
+						ContainerName:  service.Name,
+						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 {
+	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
 	loadBalancerName := fmt.Sprintf("%.32s", fmt.Sprintf("%sLoadBalancer", strings.Title(project.Name)))

+ 16 - 7
ecs/pkg/amazon/backend/cloudformation_test.go

@@ -26,13 +26,6 @@ func TestSimpleConvert(t *testing.T) {
 	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) {
 	template := convertYaml(t, "test", `
 version: "3"
@@ -94,6 +87,22 @@ services:
 	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) {
 	template := convertYaml(t, "test", `
 version: "3"

+ 0 - 4
ecs/pkg/amazon/backend/testdata/input/simple-single-service-with-overrides.yaml

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

+ 3 - 1
ecs/pkg/amazon/backend/testdata/input/simple-single-service.yaml

@@ -1,4 +1,6 @@
 version: "3"
 services:
   simple:
-    image: nginx
+    image: nginx
+    ports:
+      - "80:80"

+ 79 - 1
ecs/pkg/amazon/backend/testdata/simple/simple-cloudformation-conversion.golden

@@ -71,6 +71,9 @@
       "Type": "AWS::Logs::LogGroup"
     },
     "SimpleService": {
+      "DependsOn": [
+        "SimpleTCP80Listener"
+      ],
       "Properties": {
         "Cluster": {
           "Fn::If": [
@@ -85,6 +88,15 @@
         },
         "DesiredCount": 1,
         "LaunchType": "FARGATE",
+        "LoadBalancers": [
+          {
+            "ContainerName": "simple",
+            "ContainerPort": 80,
+            "TargetGroupArn": {
+              "Ref": "SimpleTCP80TargetGroup"
+            }
+          }
+        ],
         "NetworkConfiguration": {
           "AwsvpcConfiguration": {
             "AssignPublicIp": "ENABLED",
@@ -152,6 +164,56 @@
       },
       "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": {
       "Properties": {
         "ContainerDefinitions": [
@@ -188,7 +250,14 @@
                 "awslogs-stream-prefix": "TestSimpleConvert"
               }
             },
-            "Name": "simple"
+            "Name": "simple",
+            "PortMappings": [
+              {
+                "ContainerPort": 80,
+                "HostPort": 80,
+                "Protocol": "tcp"
+              }
+            ]
           }
         ],
         "Cpu": "256",
@@ -231,6 +300,15 @@
       "Properties": {
         "GroupDescription": "TestSimpleConvert default Security Group",
         "GroupName": "TestSimpleConvertDefaultNetwork",
+        "SecurityGroupIngress": [
+          {
+            "CidrIp": "0.0.0.0/0",
+            "Description": "simple:80/tcp",
+            "FromPort": 80,
+            "IpProtocol": "TCP",
+            "ToPort": 80
+          }
+        ],
         "Tags": [
           {
             "Key": "com.docker.compose.project",

+ 0 - 292
ecs/pkg/amazon/backend/testdata/simple/simple-cloudformation-with-overrides-conversion.golden

@@ -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"
-    }
-  }
-}