From 5ed328d8df46cf2bc7ebd47369963135d48b57a0 Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Tue, 11 Aug 2020 15:48:12 +0200 Subject: [PATCH] Add service.env_file support Signed-off-by: Nicolas De Loof --- ecs/go.mod | 1 + ecs/pkg/amazon/backend/cloudformation_test.go | 30 ++++++++ ecs/pkg/amazon/backend/compatibility.go | 1 + ecs/pkg/amazon/backend/convert.go | 74 +++++++++++++------ ecs/pkg/amazon/backend/testdata/input/envfile | 1 + 5 files changed, 85 insertions(+), 22 deletions(-) create mode 100644 ecs/pkg/amazon/backend/testdata/input/envfile diff --git a/ecs/go.mod b/ecs/go.mod index 06637206..594aa539 100644 --- a/ecs/go.mod +++ b/ecs/go.mod @@ -29,6 +29,7 @@ require ( github.com/gorilla/mux v1.7.3 // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect github.com/jinzhu/gorm v1.9.12 // indirect + github.com/joho/godotenv v1.3.0 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect github.com/lib/pq v1.3.0 // indirect github.com/manifoldco/promptui v0.7.0 diff --git a/ecs/pkg/amazon/backend/cloudformation_test.go b/ecs/pkg/amazon/backend/cloudformation_test.go index 880de0d6..84ddf530 100644 --- a/ecs/pkg/amazon/backend/cloudformation_test.go +++ b/ecs/pkg/amazon/backend/cloudformation_test.go @@ -26,6 +26,36 @@ func TestSimpleConvert(t *testing.T) { golden.Assert(t, result, expected) } +func TestEnvFile(t *testing.T) { + template := convertYaml(t, "test", ` +services: + foo: + image: hello_world + env_file: + - testdata/input/envfile +`) + def := template.Resources["FooTaskDefinition"].(*ecs.TaskDefinition) + env := def.ContainerDefinitions[0].Environment + assert.Equal(t, env[0].Name, "FOO") + assert.Equal(t, env[0].Value, "BAR") +} + +func TestEnvFileAndEnv(t *testing.T) { + template := convertYaml(t, "test", ` +services: + foo: + image: hello_world + env_file: + - testdata/input/envfile + environment: + - "FOO=ZOT" +`) + def := template.Resources["FooTaskDefinition"].(*ecs.TaskDefinition) + env := def.ContainerDefinitions[0].Environment + assert.Equal(t, env[0].Name, "FOO") + assert.Equal(t, env[0].Value, "ZOT") +} + func TestRollingUpdateLimits(t *testing.T) { template := convertYaml(t, "test", ` services: diff --git a/ecs/pkg/amazon/backend/compatibility.go b/ecs/pkg/amazon/backend/compatibility.go index 6857c498..02ef5e50 100644 --- a/ecs/pkg/amazon/backend/compatibility.go +++ b/ecs/pkg/amazon/backend/compatibility.go @@ -26,6 +26,7 @@ var compatibleComposeAttributes = []string{ "services.deploy.update_config.parallelism", "services.entrypoint", "services.environment", + "services.env_file", "service.image", "services.init", "services.healthcheck", diff --git a/ecs/pkg/amazon/backend/convert.go b/ecs/pkg/amazon/backend/convert.go index 3eddde17..b130d51a 100644 --- a/ecs/pkg/amazon/backend/convert.go +++ b/ecs/pkg/amazon/backend/convert.go @@ -3,13 +3,13 @@ package backend import ( "encoding/json" "fmt" + "os" + "path/filepath" "sort" "strconv" "strings" "time" - "github.com/docker/ecs-plugin/secrets" - "github.com/aws/aws-sdk-go/aws" ecsapi "github.com/aws/aws-sdk-go/service/ecs" "github.com/awslabs/goformation/v4/cloudformation" @@ -18,6 +18,8 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/docker/cli/opts" "github.com/docker/ecs-plugin/pkg/compose" + "github.com/docker/ecs-plugin/secrets" + "github.com/joho/godotenv" ) const secretsInitContainerImage = "docker/ecs-secrets-sidecar" @@ -121,6 +123,11 @@ func Convert(project *types.Project, service types.ServiceConfig) (*ecs.TaskDefi }) } + pairs, err := createEnvironment(project, service) + if err != nil { + return nil, err + } + containers = append(containers, ecs.TaskDefinition_ContainerDefinition{ Command: service.Command, DisableNetworking: service.NetworkMode == "none", @@ -129,7 +136,7 @@ func Convert(project *types.Project, service types.ServiceConfig) (*ecs.TaskDefi DnsServers: service.DNS, DockerSecurityOptions: service.SecurityOpt, EntryPoint: service.Entrypoint, - Environment: toKeyValuePair(service.Environment), + Environment: pairs, Essential: true, ExtraHosts: toHostEntryPtr(service.ExtraHosts), FirelensConfiguration: nil, @@ -173,6 +180,48 @@ func Convert(project *types.Project, service types.ServiceConfig) (*ecs.TaskDefi }, nil } +func createEnvironment(project *types.Project, service types.ServiceConfig) ([]ecs.TaskDefinition_KeyValuePair, error) { + environment := map[string]*string{} + for _, f := range service.EnvFile { + if !filepath.IsAbs(f) { + f = filepath.Join(project.WorkingDir, f) + } + if _, err := os.Stat(f); os.IsNotExist(err) { + return nil, err + } + file, err := os.Open(f) + if err != nil { + return nil, err + } + defer file.Close() + + env, err := godotenv.Parse(file) + if err != nil { + return nil, err + } + for k, v := range env { + environment[k] = &v + } + } + for k, v := range service.Environment { + environment[k] = v + } + + var pairs []ecs.TaskDefinition_KeyValuePair + for k, v := range environment { + name := k + var value string + if v != nil { + value = *v + } + pairs = append(pairs, ecs.TaskDefinition_KeyValuePair{ + Name: name, + Value: value, + }) + } + return pairs, nil +} + func toTags(labels types.Labels) []tags.Tag { t := []tags.Tag{} for n, v := range labels { @@ -391,25 +440,6 @@ func toHostEntryPtr(hosts types.HostsList) []ecs.TaskDefinition_HostEntry { return e } -func toKeyValuePair(environment types.MappingWithEquals) []ecs.TaskDefinition_KeyValuePair { - if environment == nil || len(environment) == 0 { - return nil - } - pairs := []ecs.TaskDefinition_KeyValuePair{} - for k, v := range environment { - name := k - var value string - if v != nil { - value = *v - } - pairs = append(pairs, ecs.TaskDefinition_KeyValuePair{ - Name: name, - Value: value, - }) - } - return pairs -} - func getRepoCredentials(service types.ServiceConfig) *ecs.TaskDefinition_RepositoryCredentials { // extract registry and namespace string from image name for key, value := range service.Extensions { diff --git a/ecs/pkg/amazon/backend/testdata/input/envfile b/ecs/pkg/amazon/backend/testdata/input/envfile new file mode 100644 index 00000000..6ac867af --- /dev/null +++ b/ecs/pkg/amazon/backend/testdata/input/envfile @@ -0,0 +1 @@ +FOO=BAR