From b702065075b07f3ec7e52dc0604badae829e0628 Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Wed, 3 Jun 2020 14:31:19 +0200 Subject: [PATCH] custom extension to select existing VPC and SecurityGroups Signed-off-by: Nicolas De Loof --- ecs/pkg/amazon/cloudformation.go | 26 ++++++++++--------- ecs/pkg/amazon/convert.go | 2 +- .../simple-cloudformation-conversion.golden | 4 +-- ...formation-with-overrides-conversion.golden | 4 +-- ecs/pkg/amazon/up.go | 21 +++++++-------- ecs/pkg/amazon/x.go | 7 +++++ 6 files changed, 35 insertions(+), 29 deletions(-) create mode 100644 ecs/pkg/amazon/x.go diff --git a/ecs/pkg/amazon/cloudformation.go b/ecs/pkg/amazon/cloudformation.go index 87d9f0600..84d0b767d 100644 --- a/ecs/pkg/amazon/cloudformation.go +++ b/ecs/pkg/amazon/cloudformation.go @@ -57,11 +57,11 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err */ template.Parameters[ParameterSubnet1Id] = cloudformation.Parameter{ Type: "AWS::EC2::Subnet::Id", - Description: "SubnetId,for Availability Zone 1 in the region in your VPC", + Description: "SubnetId, for Availability Zone 1 in the region in your VPC", } template.Parameters[ParameterSubnet2Id] = cloudformation.Parameter{ Type: "AWS::EC2::Subnet::Id", - Description: "SubnetId,for Availability Zone 1 in the region in your VPC", + Description: "SubnetId, for Availability Zone 2 in the region in your VPC", } // Create Cluster is `ParameterClusterName` parameter is not set @@ -79,10 +79,9 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err } cluster := cloudformation.If("CreateCluster", cloudformation.Ref("Cluster"), cloudformation.Ref(ParameterClusterName)) + networks := map[string]string{} for _, net := range project.Networks { - for k, v := range convertNetwork(project, net, cloudformation.Ref(ParameterVPCId)) { - template.Resources[k] = v - } + networks[net.Name] = convertNetwork(project, net, cloudformation.Ref(ParameterVPCId), template) } logGroup := fmt.Sprintf("/docker-compose/%s", project.Name) @@ -166,8 +165,7 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err serviceSecurityGroups := []string{} for net := range service.Networks { - logicalName := networkResourceName(project, net) - serviceSecurityGroups = append(serviceSecurityGroups, cloudformation.Ref(logicalName)) + serviceSecurityGroups = append(serviceSecurityGroups, networks[net]) } desiredCount := 1 @@ -213,8 +211,12 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err return template, nil } -func convertNetwork(project *compose.Project, net types.NetworkConfig, vpc string) map[string]cloudformation.Resource { - resources := map[string]cloudformation.Resource{} +func convertNetwork(project *compose.Project, net types.NetworkConfig, vpc string, template *cloudformation.Template) string { + if sg, ok := net.Extras[ExtensionSecurityGroup]; ok { + logrus.Debugf("Security Group for network %q set by user to %q", net.Name, sg) + return sg.(string) + } + var ingresses []ec2.SecurityGroup_Ingress if !net.Internal { for _, service := range project.Services { @@ -233,7 +235,7 @@ func convertNetwork(project *compose.Project, net types.NetworkConfig, vpc strin } securityGroup := networkResourceName(project, net.Name) - resources[securityGroup] = &ec2.SecurityGroup{ + template.Resources[securityGroup] = &ec2.SecurityGroup{ GroupDescription: fmt.Sprintf("%s %s Security Group", project.Name, net.Name), GroupName: securityGroup, SecurityGroupIngress: ingresses, @@ -251,14 +253,14 @@ func convertNetwork(project *compose.Project, net types.NetworkConfig, vpc strin } ingress := securityGroup + "Ingress" - resources[ingress] = &ec2.SecurityGroupIngress{ + template.Resources[ingress] = &ec2.SecurityGroupIngress{ Description: fmt.Sprintf("Allow communication within network %s", net.Name), IpProtocol: "-1", // all protocols GroupId: cloudformation.Ref(securityGroup), SourceSecurityGroupId: cloudformation.Ref(securityGroup), } - return resources + return cloudformation.Ref(securityGroup) } func networkResourceName(project *compose.Project, network string) string { diff --git a/ecs/pkg/amazon/convert.go b/ecs/pkg/amazon/convert.go index 8f43d62f9..82047ddb3 100644 --- a/ecs/pkg/amazon/convert.go +++ b/ecs/pkg/amazon/convert.go @@ -318,7 +318,7 @@ func getImage(image string) string { func getRepoCredentials(service types.ServiceConfig) *ecs.TaskDefinition_RepositoryCredentials { // extract registry and namespace string from image name for key, value := range service.Extras { - if key == "x-aws-pull_credentials" { + if key == ExtensionPullCredentials { return &ecs.TaskDefinition_RepositoryCredentials{CredentialsParameter: value.(string)} } } diff --git a/ecs/pkg/amazon/testdata/simple/simple-cloudformation-conversion.golden b/ecs/pkg/amazon/testdata/simple/simple-cloudformation-conversion.golden index c1233d0a3..8a95637a6 100644 --- a/ecs/pkg/amazon/testdata/simple/simple-cloudformation-conversion.golden +++ b/ecs/pkg/amazon/testdata/simple/simple-cloudformation-conversion.golden @@ -16,11 +16,11 @@ "Type": "String" }, "ParameterSubnet1Id": { - "Description": "SubnetId,for Availability Zone 1 in the region in your VPC", + "Description": "SubnetId, for Availability Zone 1 in the region in your VPC", "Type": "AWS::EC2::Subnet::Id" }, "ParameterSubnet2Id": { - "Description": "SubnetId,for Availability Zone 1 in the region in your VPC", + "Description": "SubnetId, for Availability Zone 2 in the region in your VPC", "Type": "AWS::EC2::Subnet::Id" }, "ParameterVPCId": { diff --git a/ecs/pkg/amazon/testdata/simple/simple-cloudformation-with-overrides-conversion.golden b/ecs/pkg/amazon/testdata/simple/simple-cloudformation-with-overrides-conversion.golden index ca03c1176..a5551ddcb 100644 --- a/ecs/pkg/amazon/testdata/simple/simple-cloudformation-with-overrides-conversion.golden +++ b/ecs/pkg/amazon/testdata/simple/simple-cloudformation-with-overrides-conversion.golden @@ -16,11 +16,11 @@ "Type": "String" }, "ParameterSubnet1Id": { - "Description": "SubnetId,for Availability Zone 1 in the region in your VPC", + "Description": "SubnetId, for Availability Zone 1 in the region in your VPC", "Type": "AWS::EC2::Subnet::Id" }, "ParameterSubnet2Id": { - "Description": "SubnetId,for Availability Zone 1 in the region in your VPC", + "Description": "SubnetId, for Availability Zone 2 in the region in your VPC", "Type": "AWS::EC2::Subnet::Id" }, "ParameterVPCId": { diff --git a/ecs/pkg/amazon/up.go b/ecs/pkg/amazon/up.go index 23517a118..21500c381 100644 --- a/ecs/pkg/amazon/up.go +++ b/ecs/pkg/amazon/up.go @@ -59,18 +59,15 @@ func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error } func (c client) GetVPC(ctx context.Context, project *compose.Project) (string, error) { - //check compose file for the default external network - if net, ok := project.Networks["default"]; ok { - if net.External.External { - vpc := net.Name - ok, err := c.api.VpcExists(ctx, vpc) - if err != nil { - return "", err - } - if !ok { - return "", fmt.Errorf("VPC does not exist: %s", vpc) - } - return vpc, nil + //check compose file for custom VPC selected + if vpc, ok := project.Extras[ExtensionVPC]; ok { + vpcID := vpc.(string) + ok, err := c.api.VpcExists(ctx, vpcID) + if err != nil { + return "", err + } + if !ok { + return "", fmt.Errorf("VPC does not exist: %s", vpc) } } defaultVPC, err := c.api.GetDefaultVPC(ctx) diff --git a/ecs/pkg/amazon/x.go b/ecs/pkg/amazon/x.go new file mode 100644 index 000000000..0b022bac2 --- /dev/null +++ b/ecs/pkg/amazon/x.go @@ -0,0 +1,7 @@ +package amazon + +const ( + ExtensionSecurityGroup = "x-aws-securitygroup" + ExtensionVPC = "x-aws-vpc" + ExtensionPullCredentials = "x-aws-pull_credentials" +)