Create cluster by compose up

close #53

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2020-05-13 10:34:23 +02:00
parent 1fdac494f3
commit 43d3d94c43
No known key found for this signature in database
GPG Key ID: 9858809D6F8F6E7E
2 changed files with 50 additions and 18 deletions

View File

@ -17,9 +17,23 @@ import (
"github.com/docker/ecs-plugin/pkg/compose" "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) { func (c client) Convert(project *compose.Project) (*cloudformation.Template, error) {
template := cloudformation.NewTemplate() 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", Type: "AWS::EC2::VPC::Id",
Description: "ID of the VPC", 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", 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", 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["Subnet2Id"] = cloudformation.Parameter{ template.Parameters[ParameterSubnet2Id] = cloudformation.Parameter{
Type: "AWS::EC2::Subnet::Id", 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",
} }
// 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 { 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 template.Resources[name] = resource
} }
@ -54,7 +83,7 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err
template.Resources["CloudMap"] = &cloudmap.PrivateDnsNamespace{ template.Resources["CloudMap"] = &cloudmap.PrivateDnsNamespace{
Description: fmt.Sprintf("Service Map for Docker Compose project %s", project.Name), Description: fmt.Sprintf("Service Map for Docker Compose project %s", project.Name),
Name: fmt.Sprintf("%s.local", project.Name), Name: fmt.Sprintf("%s.local", project.Name),
Vpc: cloudformation.Ref("VPCId"), Vpc: cloudformation.Ref(ParameterVPCId),
} }
for _, service := range project.Services { 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{ template.Resources[fmt.Sprintf("%sService", service.Name)] = &ecs.Service{
Cluster: c.Cluster, Cluster: cluster,
DesiredCount: 1, DesiredCount: 1,
LaunchType: ecsapi.LaunchTypeFargate, LaunchType: ecsapi.LaunchTypeFargate,
NetworkConfiguration: &ecs.Service_NetworkConfiguration{ NetworkConfiguration: &ecs.Service_NetworkConfiguration{
@ -125,8 +154,8 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err
AssignPublicIp: ecsapi.AssignPublicIpEnabled, AssignPublicIp: ecsapi.AssignPublicIpEnabled,
SecurityGroups: serviceSecurityGroups, SecurityGroups: serviceSecurityGroups,
Subnets: []string{ Subnets: []string{
cloudformation.Ref("Subnet1Id"), cloudformation.Ref(ParameterSubnet1Id),
cloudformation.Ref("Subnet2Id"), cloudformation.Ref(ParameterSubnet2Id),
}, },
}, },
}, },

View File

@ -9,13 +9,16 @@ import (
) )
func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error { func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error {
ok, err := c.api.ClusterExists(ctx, c.Cluster) if c.Cluster != "" {
if err != nil { ok, err := c.api.ClusterExists(ctx, c.Cluster)
return err if err != nil {
} return err
if !ok { }
c.api.CreateCluster(ctx, c.Cluster) if !ok {
return fmt.Errorf("configured cluster %q does not exist", c.Cluster)
}
} }
update, err := c.api.StackExists(ctx, project.Name) update, err := c.api.StackExists(ctx, project.Name)
if err != nil { if err != nil {
return err return err
@ -45,9 +48,10 @@ func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error
} }
parameters := map[string]string{ parameters := map[string]string{
"VPCId": vpc, ParameterClusterName: c.Cluster,
"Subnet1Id": subNets[0], ParameterVPCId: vpc,
"Subnet2Id": subNets[1], ParameterSubnet1Id: subNets[0],
ParameterSubnet2Id: subNets[1],
} }
err = c.api.CreateStack(ctx, project.Name, template, parameters) err = c.api.CreateStack(ctx, project.Name, template, parameters)
@ -87,7 +91,6 @@ type upAPI interface {
GetSubNets(ctx context.Context, vpcID string) ([]string, error) GetSubNets(ctx context.Context, vpcID string) ([]string, error)
ClusterExists(ctx context.Context, name string) (bool, 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) StackExists(ctx context.Context, name string) (bool, error)
CreateStack(ctx context.Context, name string, template *cloudformation.Template, parameters map[string]string) error CreateStack(ctx context.Context, name string, template *cloudformation.Template, parameters map[string]string) error
} }