Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(compose): Add EFS volume support to ECS Params. #1019

Merged
merged 19 commits into from May 26, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
69 changes: 55 additions & 14 deletions ecs-cli/modules/utils/compose/convert_task_definition.go
Expand Up @@ -262,42 +262,83 @@ func convertToECSSecrets(secrets []Secret) []*ecs.Secret {
}

func mergeVolumesWithoutHost(composeVolumes []string, ecsParams *ECSParams) ([]*ecs.Volume, error) {
volumesWithoutHost := make(map[string]DockerVolume)
volumesWithoutHost := make(map[string]Volume)
output := []*ecs.Volume{}

for _, volName := range composeVolumes {
volumesWithoutHost[volName] = DockerVolume{}
volumesWithoutHost[volName] = Volume{}
}

if ecsParams != nil {
for _, dockerVol := range ecsParams.TaskDefinition.DockerVolumes {
if dockerVol.Name != "" {
volumesWithoutHost[dockerVol.Name] = dockerVol
volumesWithoutHost[dockerVol.Name] = Volume{DockerVolumeConfig: dockerVol}
} else {
return nil, fmt.Errorf("Name is required when specifying a docker volume")
}
}
for _, efsVol := range ecsParams.TaskDefinition.EFSVolumes {
if efsVol.Name != "" {
volumesWithoutHost[efsVol.Name] = Volume{EFSVolumeConfig: efsVol}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we return an error similar to that on line 282 if no name is specified?

}
}

var dVolCfg DockerVolume
var efsVolCfg EFSVolume
for volName, dVol := range volumesWithoutHost {
SoManyHs marked this conversation as resolved.
Show resolved Hide resolved
ecsVolume := &ecs.Volume{
Name: aws.String(volName),
}
if dVol.Name != "" {
dVolCfg = dVol.DockerVolumeConfig
efsVolCfg = dVol.EFSVolumeConfig
if dVolCfg.Name != "" {
ecsVolume.DockerVolumeConfiguration = &ecs.DockerVolumeConfiguration{
Autoprovision: dVol.Autoprovision,
Autoprovision: dVolCfg.Autoprovision,
}
if dVolCfg.Driver != nil {
ecsVolume.DockerVolumeConfiguration.Driver = dVolCfg.Driver
}
if dVolCfg.Scope != nil {
ecsVolume.DockerVolumeConfiguration.Scope = dVolCfg.Scope
}
if dVolCfg.DriverOptions != nil {
ecsVolume.DockerVolumeConfiguration.DriverOpts = aws.StringMap(dVolCfg.DriverOptions)
}
if dVolCfg.Labels != nil {
ecsVolume.DockerVolumeConfiguration.Labels = aws.StringMap(dVolCfg.Labels)
}
}
if efsVolCfg.Name != "" {
ecsVolume.EfsVolumeConfiguration = &ecs.EFSVolumeConfiguration{}
if efsVolCfg.FileSystemID != nil {
ecsVolume.EfsVolumeConfiguration.FileSystemId = efsVolCfg.FileSystemID
} else {
return nil, fmt.Errorf("file system id is required for efs volumes")
}
if efsVolCfg.RootDirectory != nil {
ecsVolume.EfsVolumeConfiguration.RootDirectory = efsVolCfg.RootDirectory
}
var transitEncryptionRequired = false
efsAuthCfg := &ecs.EFSAuthorizationConfig{}
if efsVolCfg.IAM != nil {
efsAuthCfg.Iam = efsVolCfg.IAM
if *efsVolCfg.IAM == "ENABLED" {
transitEncryptionRequired = true
}
}
if dVol.Driver != nil {
ecsVolume.DockerVolumeConfiguration.Driver = dVol.Driver
if efsVolCfg.AccessPointID != nil {
efsAuthCfg.AccessPointId = efsVolCfg.AccessPointID
transitEncryptionRequired = true
}
if dVol.Scope != nil {
ecsVolume.DockerVolumeConfiguration.Scope = dVol.Scope
ecsVolume.EfsVolumeConfiguration.AuthorizationConfig = efsAuthCfg
if efsVolCfg.TransitEncryption != nil {
ecsVolume.EfsVolumeConfiguration.TransitEncryption = efsVolCfg.TransitEncryption
}
if dVol.DriverOptions != nil {
ecsVolume.DockerVolumeConfiguration.DriverOpts = aws.StringMap(dVol.DriverOptions)
if transitEncryptionRequired && *efsVolCfg.TransitEncryption != "ENABLED" {
return nil, fmt.Errorf("Transit encryption is required when using IAM access or an access point")
}
if dVol.Labels != nil {
ecsVolume.DockerVolumeConfiguration.Labels = aws.StringMap(dVol.Labels)
if efsVolCfg.TransitEncryptionPort != nil {
ecsVolume.EfsVolumeConfiguration.TransitEncryptionPort = efsVolCfg.TransitEncryptionPort
}
}
output = append(output, ecsVolume)
Expand Down
16 changes: 16 additions & 0 deletions ecs-cli/modules/utils/compose/ecs_params_reader.go
Expand Up @@ -51,6 +51,7 @@ type EcsTaskDef struct {
ExecutionRole string `yaml:"task_execution_role"`
TaskSize TaskSize `yaml:"task_size"` // Needed to run FARGATE tasks
DockerVolumes []DockerVolume `yaml:"docker_volumes"`
EFSVolumes []EFSVolume `yaml:"efs_volumes"`
PlacementConstraints []Constraint `yaml:"placement_constraints"`
}

Expand All @@ -73,6 +74,11 @@ type ContainerDef struct {
GPU string `yaml:"gpu"`
}

type Volume struct {
DockerVolumeConfig DockerVolume
EFSVolumeConfig EFSVolume
}

type DockerVolume struct {
Name string `yaml:"name"`
Scope *string `yaml:"scope"`
Expand All @@ -82,6 +88,16 @@ type DockerVolume struct {
Labels map[string]string `yaml:"labels"`
}

type EFSVolume struct {
Name string `yaml:"name"`
FileSystemID *string `yaml:"filesystem_id"` // Required
RootDirectory *string `yaml:"root_directory"`
TransitEncryption *string `yaml:"transit_encryption"` // Optional. default: DISABLED. options: ENABLED or DISABLED
TransitEncryptionPort *int64 `yaml:"transit_encryption_port"`
AccessPointID *string `yaml:"access_point"`
IAM *string `yaml:"iam"` // default: DISABLED. options: ENABLED or DISABLED
}

// Firelens holds all possible fields for logging via Firelens
// https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_FirelensConfiguration.html
type FirelensConfiguration struct {
Expand Down