Browse Source

allow user defined LB

Signed-off-by: aiordache <[email protected]>
Signed-off-by: Nicolas De Loof <[email protected]>
aiordache 5 years ago
parent
commit
3194cc9b16
4 changed files with 82 additions and 15 deletions
  1. 30 11
      ecs/pkg/amazon/cloudformation.go
  2. 22 0
      ecs/pkg/amazon/sdk.go
  3. 29 4
      ecs/pkg/amazon/up.go
  4. 1 0
      ecs/pkg/amazon/x.go

+ 30 - 11
ecs/pkg/amazon/cloudformation.go

@@ -25,10 +25,11 @@ import (
 )
 
 const (
-	ParameterClusterName = "ParameterClusterName"
-	ParameterVPCId       = "ParameterVPCId"
-	ParameterSubnet1Id   = "ParameterSubnet1Id"
-	ParameterSubnet2Id   = "ParameterSubnet2Id"
+	ParameterClusterName     = "ParameterClusterName"
+	ParameterVPCId           = "ParameterVPCId"
+	ParameterSubnet1Id       = "ParameterSubnet1Id"
+	ParameterSubnet2Id       = "ParameterSubnet2Id"
+	ParameterLoadBalancerARN = "ParameterLoadBalancerARN"
 )
 
 // Convert a compose project into a CloudFormation template
@@ -66,6 +67,11 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err
 		Description: "SubnetId, for Availability Zone 2 in the region in your VPC",
 	}
 
+	template.Parameters[ParameterLoadBalancerARN] = cloudformation.Parameter{
+		Type:        "String",
+		Description: "Name of the LoadBalancer to connect to (optional)",
+	}
+
 	// Create Cluster is `ParameterClusterName` parameter is not set
 	template.Conditions["CreateCluster"] = cloudformation.Equals("", cloudformation.Ref(ParameterClusterName))
 
@@ -172,10 +178,19 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err
 }
 
 func (c client) createLoadBalancer(project *compose.Project, template *cloudformation.Template) string {
-	loadBalancerName := fmt.Sprintf("%sLoadBalancer", strings.Title(project.Name))
-	template.Resources[loadBalancerName] = &elasticloadbalancingv2.LoadBalancer{
+
+	loadBalancerType := "network"
+	loadBalancerName := fmt.Sprintf(
+		"%s%sLB",
+		strings.Title(project.Name),
+		strings.ToUpper(loadBalancerType[0:1]),
+	)
+	// Create LoadBalancer if `ParameterLoadBalancerName` is not set
+	template.Conditions["CreateLoadBalancer"] = cloudformation.Equals("", cloudformation.Ref(ParameterLoadBalancerARN))
+
+	loadBalancer := &elasticloadbalancingv2.LoadBalancer{
 		Name:   loadBalancerName,
-		Scheme: elbv2.LoadBalancerSchemeEnumInternetFacing,
+		Scheme: "internet-facing",
 		Subnets: []string{
 			cloudformation.Ref(ParameterSubnet1Id),
 			cloudformation.Ref(ParameterSubnet2Id),
@@ -186,12 +201,16 @@ func (c client) createLoadBalancer(project *compose.Project, template *cloudform
 				Value: project.Name,
 			},
 		},
-		Type: elbv2.LoadBalancerTypeEnumNetwork,
+		Type:                       loadBalancerType,
+		AWSCloudFormationCondition: "CreateLoadBalancer",
 	}
-	return loadBalancerName
+	template.Resources[loadBalancerName] = loadBalancer
+	loadBalancerRef := cloudformation.If("CreateLoadBalancer", cloudformation.Ref(loadBalancerName), cloudformation.Ref(ParameterLoadBalancerARN))
+
+	return loadBalancerRef
 }
 
-func (c client) createListener(service types.ServiceConfig, port types.ServicePortConfig, template *cloudformation.Template, targetGroupName string, loadBalancerName string, protocol string) string {
+func (c client) createListener(service types.ServiceConfig, port types.ServicePortConfig, template *cloudformation.Template, targetGroupName string, loadBalancerARN string, protocol string) string {
 	listenerName := fmt.Sprintf(
 		"%s%s%dListener",
 		normalizeResourceName(service.Name),
@@ -213,7 +232,7 @@ func (c client) createListener(service types.ServiceConfig, port types.ServicePo
 				Type: elbv2.ActionTypeEnumForward,
 			},
 		},
-		LoadBalancerArn: cloudformation.Ref(loadBalancerName),
+		LoadBalancerArn: loadBalancerARN,
 		Protocol:        protocol,
 		Port:            int(port.Published),
 	}

+ 22 - 0
ecs/pkg/amazon/sdk.go

@@ -400,3 +400,25 @@ func (s sdk) GetPublicIPs(ctx context.Context, interfaces ...string) (map[string
 	}
 	return publicIPs, nil
 }
+
+func (s sdk) LoadBalancerExists(ctx context.Context, name string) (bool, error) {
+	logrus.Debug("Check if cluster was already created: ", name)
+	lbs, err := s.ELB.DescribeLoadBalancersWithContext(ctx, &elbv2.DescribeLoadBalancersInput{
+		Names: []*string{aws.String(name)},
+	})
+	if err != nil {
+		return false, err
+	}
+	return len(lbs.LoadBalancers) > 0, nil
+}
+
+func (s sdk) GetLoadBalancerARN(ctx context.Context, name string) (string, error) {
+	logrus.Debug("Check if cluster was already created: ", name)
+	lbs, err := s.ELB.DescribeLoadBalancersWithContext(ctx, &elbv2.DescribeLoadBalancersInput{
+		Names: []*string{aws.String(name)},
+	})
+	if err != nil {
+		return "", err
+	}
+	return *lbs.LoadBalancers[0].LoadBalancerArn, nil
+}

+ 29 - 4
ecs/pkg/amazon/up.go

@@ -42,11 +42,17 @@ func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error
 		return err
 	}
 
+	lb, err := c.GetLoadBalancer(ctx, project)
+	if err != nil {
+		return err
+	}
+
 	parameters := map[string]string{
-		ParameterClusterName: c.Cluster,
-		ParameterVPCId:       vpc,
-		ParameterSubnet1Id:   subNets[0],
-		ParameterSubnet2Id:   subNets[1],
+		ParameterClusterName:     c.Cluster,
+		ParameterVPCId:           vpc,
+		ParameterSubnet1Id:       subNets[0],
+		ParameterSubnet2Id:       subNets[1],
+		ParameterLoadBalancerARN: lb,
 	}
 
 	err = c.api.CreateStack(ctx, project.Name, template, parameters)
@@ -77,6 +83,22 @@ func (c client) GetVPC(ctx context.Context, project *compose.Project) (string, e
 	return defaultVPC, nil
 }
 
+func (c client) GetLoadBalancer(ctx context.Context, project *compose.Project) (string, error) {
+	//check compose file for custom VPC selected
+	if lb, ok := project.Extras[ExtensionLB]; ok {
+		lbName := lb.(string)
+		ok, err := c.api.LoadBalancerExists(ctx, lbName)
+		if err != nil {
+			return "", err
+		}
+		if !ok {
+			return "", fmt.Errorf("Load Balancer does not exist: %s", lb)
+		}
+		return c.api.GetLoadBalancerARN(ctx, lbName)
+	}
+	return "", nil
+}
+
 type upAPI interface {
 	waitAPI
 	GetDefaultVPC(ctx context.Context) (string, error)
@@ -86,4 +108,7 @@ type upAPI interface {
 	ClusterExists(ctx context.Context, name string) (bool, error)
 	StackExists(ctx context.Context, name string) (bool, error)
 	CreateStack(ctx context.Context, name string, template *cloudformation.Template, parameters map[string]string) error
+
+	LoadBalancerExists(ctx context.Context, name string) (bool, error)
+	GetLoadBalancerARN(ctx context.Context, name string) (string, error)
 }

+ 1 - 0
ecs/pkg/amazon/x.go

@@ -4,4 +4,5 @@ const (
 	ExtensionSecurityGroup   = "x-aws-securitygroup"
 	ExtensionVPC             = "x-aws-vpc"
 	ExtensionPullCredentials = "x-aws-pull_credentials"
+	ExtensionLB              = "x-aws-lb"
 )