Repository: compose-spec/compose-go
Pull request #60 (2020-07-13 15:52:56)

Discard a service's env_file using project options.
The `discardEnvFiles` `loader.Load` option is not visible to developers wanting to create a project using `cli.ProjectFromOptions(&projectOptions)`.

This PR,

- Adds the `loadOptions` property to the `ProjectOptions` struct.

- Enables discarding the `env_file` using the new `WithDiscardEnvFile` method.

- `WithDiscardEnvFile` adds `loader.WithDiscardEnvFiles` func to `ProjectOptions.loadOptions`.

- Then the load options are passed to `loader.load` in the `ProjectFromOptions` func.

ndeloof: note: `loader.Options#discardEnvFiles` was introduced by https://github.com/docker/cli/commit/821f5ecf53c87a1f391d97c358f08c8d344cda8c

Makes perfect sense to me to introduce `LoadOptions` in `ProjectOptions` (we should define a func type for it)
ndeloof: I'm sorry I didn't reviewed this before, could you please rebase then I can merge ?
ezodude: @ndeloof all done.

Patch:
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ad5395b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+### IDEs ###
+.idea/*
diff --git a/cli/options.go b/cli/options.go
index 5380268..3817109 100644
--- a/cli/options.go
+++ b/cli/options.go
@@ -38,6 +38,7 @@ type ProjectOptions struct {
 	WorkingDir  string
 	ConfigPaths []string
 	Environment map[string]string
+	loadOptions []func(*loader.Options)
 }
 
 type ProjectOptionsFn func(*ProjectOptions) error
@@ -83,6 +84,13 @@ func WithEnv(env []string) ProjectOptionsFn {
 	}
 }
 
+// WithDiscardEnvFiles sets discards the `env_file` section after resolving to
+// the `environment` section
+func WithDiscardEnvFile(o *ProjectOptions) error {
+	o.loadOptions = append(o.loadOptions, loader.WithDiscardEnvFiles)
+	return nil
+}
+
 // WithOsEnv imports environment variables from OS
 func WithOsEnv(o *ProjectOptions) error {
 	for k, v := range getAsEqualsMap(os.Environ()) {
@@ -163,11 +171,7 @@ func ProjectFromOptions(options *ProjectOptions) (*types.Project, error) {
 		return nil, err
 	}
 
-	return loader.Load(types.ConfigDetails{
-		ConfigFiles: configs,
-		WorkingDir:  workingDir,
-		Environment: options.Environment,
-	}, func(opts *loader.Options) {
+	var nameLoadOpt = func(opts *loader.Options) {
 		if options.Name != "" {
 			opts.Name = options.Name
 		} else if nameFromEnv, ok := os.LookupEnv(ComposeProjectName); ok {
@@ -176,7 +180,14 @@ func ProjectFromOptions(options *ProjectOptions) (*types.Project, error) {
 			opts.Name = regexp.MustCompile(`[^a-z0-9\\-_]+`).
 				ReplaceAllString(strings.ToLower(filepath.Base(absWorkingDir)), "")
 		}
-	})
+	}
+	options.loadOptions = append(options.loadOptions, nameLoadOpt)
+
+	return loader.Load(types.ConfigDetails{
+		ConfigFiles: configs,
+		WorkingDir:  workingDir,
+		Environment: options.Environment,
+	}, options.loadOptions...)
 }
 
 // getConfigPathsFromOptions retrieves the config files for project based on project options


Test patch:
diff --git a/cli/options_test.go b/cli/options_test.go
index d83b16b..9459307 100644
--- a/cli/options_test.go
+++ b/cli/options_test.go
@@ -76,6 +76,20 @@ func TestProjectWithDotEnv(t *testing.T) {
 	assert.Equal(t, service.Ports[0].Published, uint32(8000))
 }
 
+func TestProjectWithDiscardEnvFile(t *testing.T) {
+	opts, err := NewProjectOptions([]string{
+		"testdata/env-file/compose-with-env-file.yaml",
+	}, WithDiscardEnvFile)
+
+	assert.NilError(t, err)
+	p, err := ProjectFromOptions(opts)
+	assert.NilError(t, err)
+	service, err := p.GetService("simple")
+	assert.NilError(t, err)
+	assert.Equal(t, *service.Environment["DEFAULT_PORT"], "8080")
+	assert.Assert(t, service.EnvFile == nil)
+}
+
 func TestEnvMap(t *testing.T) {
 	m := map[string]string{}
 	m["foo"] = "bar"
diff --git a/cli/testdata/env-file/compose-with-env-file.yaml b/cli/testdata/env-file/compose-with-env-file.yaml
new file mode 100644
index 0000000..5d51ba9
--- /dev/null
+++ b/cli/testdata/env-file/compose-with-env-file.yaml
@@ -0,0 +1,8 @@
+version: "3"
+services:
+  simple:
+    image: nginx
+    env_file:
+      - ./simple-env
+    ports:
+    - 8000:80
diff --git a/cli/testdata/env-file/simple-env b/cli/testdata/env-file/simple-env
new file mode 100644
index 0000000..e2ba368
--- /dev/null
+++ b/cli/testdata/env-file/simple-env
@@ -0,0 +1,1 @@
+DEFAULT_PORT=8080
\ No newline at end of file