From 43d3d94c43e21166b4577a8c8b84d0a18ddff2a3 Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Wed, 13 May 2020 10:34:23 +0200 Subject: [PATCH] Create cluster by compose up close #53 Signed-off-by: Nicolas De Loof --- ecs/pkg/amazon/cloudformation.go | 45 ++++++++++++++++++++++++++------ ecs/pkg/amazon/up.go | 23 +++++++++------- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/ecs/pkg/amazon/cloudformation.go b/ecs/pkg/amazon/cloudformation.go index 075037c08..d14b5fafa 100644 --- a/ecs/pkg/amazon/cloudformation.go +++ b/ecs/pkg/amazon/cloudformation.go @@ -17,9 +17,23 @@ import ( "github.com/docker/ecs-plugin/pkg/compose" ) +const ( + ParameterClusterName = "ParameterClusterName" + ParameterVPCId = "ParameterVPCId" + ParameterSubnet1Id = "ParameterSubnet1Id" + ParameterSubnet2Id = "ParameterSubnet2Id" +) + +// Convert a compose project into a CloudFormation template func (c client) Convert(project *compose.Project) (*cloudformation.Template, error) { template := cloudformation.NewTemplate() - template.Parameters["VPCId"] = cloudformation.Parameter{ + + template.Parameters[ParameterClusterName] = cloudformation.Parameter{ + Type: "String", + Description: "Name of the ECS cluster to deploy to (optional)", + } + + template.Parameters[ParameterVPCId] = cloudformation.Parameter{ Type: "AWS::EC2::VPC::Id", Description: "ID of the VPC", } @@ -31,17 +45,32 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err Description: "The list of SubnetIds, for at least two Availability Zones in the region in your VPC", } */ - template.Parameters["Subnet1Id"] = cloudformation.Parameter{ + template.Parameters[ParameterSubnet1Id] = cloudformation.Parameter{ Type: "AWS::EC2::Subnet::Id", Description: "SubnetId,for Availability Zone 1 in the region in your VPC", } - template.Parameters["Subnet2Id"] = cloudformation.Parameter{ + template.Parameters[ParameterSubnet2Id] = cloudformation.Parameter{ Type: "AWS::EC2::Subnet::Id", Description: "SubnetId,for Availability Zone 1 in the region in your VPC", } + // Create Cluster is `ParameterClusterName` parameter is not set + template.Conditions["CreateCluster"] = cloudformation.Equals("", cloudformation.Ref(ParameterClusterName)) + + template.Resources["Cluster"] = &ecs.Cluster{ + ClusterName: project.Name, + Tags: []tags.Tag{ + { + Key: ProjectTag, + Value: project.Name, + }, + }, + AWSCloudFormationCondition: "CreateCluster", + } + cluster := cloudformation.If("CreateCluster", cloudformation.Ref("Cluster"), cloudformation.Ref(ParameterClusterName)) + for net := range project.Networks { - name, resource := convertNetwork(project, net, cloudformation.Ref("VPCId")) + name, resource := convertNetwork(project, net, cloudformation.Ref(ParameterVPCId)) template.Resources[name] = resource } @@ -54,7 +83,7 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err template.Resources["CloudMap"] = &cloudmap.PrivateDnsNamespace{ Description: fmt.Sprintf("Service Map for Docker Compose project %s", project.Name), Name: fmt.Sprintf("%s.local", project.Name), - Vpc: cloudformation.Ref("VPCId"), + Vpc: cloudformation.Ref(ParameterVPCId), } for _, service := range project.Services { @@ -117,7 +146,7 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err } template.Resources[fmt.Sprintf("%sService", service.Name)] = &ecs.Service{ - Cluster: c.Cluster, + Cluster: cluster, DesiredCount: 1, LaunchType: ecsapi.LaunchTypeFargate, NetworkConfiguration: &ecs.Service_NetworkConfiguration{ @@ -125,8 +154,8 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err AssignPublicIp: ecsapi.AssignPublicIpEnabled, SecurityGroups: serviceSecurityGroups, Subnets: []string{ - cloudformation.Ref("Subnet1Id"), - cloudformation.Ref("Subnet2Id"), + cloudformation.Ref(ParameterSubnet1Id), + cloudformation.Ref(ParameterSubnet2Id), }, }, }, diff --git a/ecs/pkg/amazon/up.go b/ecs/pkg/amazon/up.go index e1a0f1fd6..2ad74ba8d 100644 --- a/ecs/pkg/amazon/up.go +++ b/ecs/pkg/amazon/up.go @@ -9,13 +9,16 @@ import ( ) func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error { - ok, err := c.api.ClusterExists(ctx, c.Cluster) - if err != nil { - return err - } - if !ok { - c.api.CreateCluster(ctx, c.Cluster) + if c.Cluster != "" { + ok, err := c.api.ClusterExists(ctx, c.Cluster) + if err != nil { + return err + } + if !ok { + return fmt.Errorf("configured cluster %q does not exist", c.Cluster) + } } + update, err := c.api.StackExists(ctx, project.Name) if err != nil { return err @@ -45,9 +48,10 @@ func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error } parameters := map[string]string{ - "VPCId": vpc, - "Subnet1Id": subNets[0], - "Subnet2Id": subNets[1], + ParameterClusterName: c.Cluster, + ParameterVPCId: vpc, + ParameterSubnet1Id: subNets[0], + ParameterSubnet2Id: subNets[1], } err = c.api.CreateStack(ctx, project.Name, template, parameters) @@ -87,7 +91,6 @@ type upAPI interface { GetSubNets(ctx context.Context, vpcID string) ([]string, error) ClusterExists(ctx context.Context, name string) (bool, error) - CreateCluster(ctx context.Context, name string) (string, error) StackExists(ctx context.Context, name string) (bool, error) CreateStack(ctx context.Context, name string, template *cloudformation.Template, parameters map[string]string) error }