diff --git a/api/compose/tags.go b/api/compose/tags.go index 9e6263da..042a1409 100644 --- a/api/compose/tags.go +++ b/api/compose/tags.go @@ -23,4 +23,6 @@ const ( NetworkTag = "com.docker.compose.network" // ServiceTag allow to track resource related to a compose service ServiceTag = "com.docker.compose.service" + // VolumeTag allow to track resource related to a compose volume + VolumeTag = "com.docker.compose.volume" ) diff --git a/ecs/awsResources.go b/ecs/awsResources.go index 8f9912e5..0bd06968 100644 --- a/ecs/awsResources.go +++ b/ecs/awsResources.go @@ -38,6 +38,7 @@ type awsResources struct { loadBalancer string loadBalancerType string securityGroups map[string]string + filesystems map[string]string } func (r *awsResources) serviceSecurityGroups(service types.ServiceConfig) []string { @@ -72,7 +73,7 @@ func (b *ecsAPIService) parse(ctx context.Context, project *types.Project) (awsR if err != nil { return r, err } - r.securityGroups, err = b.parseSecurityGroupExtension(ctx, project) + r.securityGroups, err = b.parseExternalNetworks(ctx, project) if err != nil { return r, err } @@ -139,7 +140,7 @@ func (b *ecsAPIService) parseLoadBalancerExtension(ctx context.Context, project return "", "", nil } -func (b *ecsAPIService) parseSecurityGroupExtension(ctx context.Context, project *types.Project) (map[string]string, error) { +func (b *ecsAPIService) parseExternalNetworks(ctx context.Context, project *types.Project) (map[string]string, error) { securityGroups := make(map[string]string, len(project.Networks)) for name, net := range project.Networks { if !net.External.External { @@ -163,6 +164,25 @@ func (b *ecsAPIService) parseSecurityGroupExtension(ctx context.Context, project return securityGroups, nil } +func (b *ecsAPIService) parseExternalVolumes(ctx context.Context, project *types.Project) (map[string]string, error) { + filesystems := make(map[string]string, len(project.Volumes)) + // project.Volumes.filter(|v| v.External.External).first(|v| b.SDK.FileSystemExists(ctx, vol.Name))? + for name, vol := range project.Volumes { + if !vol.External.External { + continue + } + exists, err := b.SDK.FileSystemExists(ctx, vol.Name) + if err != nil { + return nil, err + } + if !exists { + return nil, fmt.Errorf("EFS file system %s doesn't exist", vol.Name) + } + filesystems[name] = vol.Name + } + return filesystems, nil +} + // ensureResources create required resources in template if not yet defined func (b *ecsAPIService) ensureResources(resources *awsResources, project *types.Project, template *cloudformation.Template) { b.ensureCluster(resources, project, template) @@ -210,6 +230,12 @@ func (b *ecsAPIService) ensureNetworks(r *awsResources, project *types.Project, } } +func (b *ecsAPIService) ensureVolumes(r *awsResources, project *types.Project, template *cloudformation.Template) { + if r.filesystems == nil { + r.filesystems = make(map[string]string, len(project.Volumes)) + } +} + func (b *ecsAPIService) ensureLoadBalancer(r *awsResources, project *types.Project, template *cloudformation.Template) { if r.loadBalancer != "" { return diff --git a/ecs/sdk.go b/ecs/sdk.go index a6abb9e1..9ceb872a 100644 --- a/ecs/sdk.go +++ b/ecs/sdk.go @@ -858,3 +858,35 @@ func (s sdk) DeleteAutoscalingGroup(ctx context.Context, arn string) error { }) return err } + +func (s sdk) FileSystemExists(ctx context.Context, id string) (bool, error) { + desc, err := s.EFS.DescribeFileSystemsWithContext(ctx, &efs.DescribeFileSystemsInput{ + FileSystemId: aws.String(id), + }) + if err != nil { + return false, err + } + return len(desc.FileSystems) > 0, nil +} + +func (s sdk) CreateFileSystem(ctx context.Context, name string) (string, error) { + res, err := s.EFS.CreateFileSystemWithContext(ctx, &efs.CreateFileSystemInput{ + Tags: []*efs.Tag{ + { + Key: aws.String(compose.VolumeTag), + Value: aws.String(name), + }, + }, + }) + if err != nil { + return "", err + } + return aws.StringValue(res.FileSystemId), nil +} + +func (s sdk) DeleteFileSystem(ctx context.Context, id string) error { + _, err := s.EFS.DeleteFileSystemWithContext(ctx, &efs.DeleteFileSystemInput{ + FileSystemId: aws.String(id), + }) + return err +}