فهرست منبع

Add service.env_file support

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 5 سال پیش
والد
کامیت
5ed328d8df

+ 1 - 0
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

+ 30 - 0
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:

+ 1 - 0
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",

+ 52 - 22
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 {

+ 1 - 0
ecs/pkg/amazon/backend/testdata/input/envfile

@@ -0,0 +1 @@
+FOO=BAR