Browse Source

Add support to pass env-from-file to docker compose run

Signed-off-by: Vedant Koditkar <[email protected]>
Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 3 years ago
parent
commit
83cafe2838

+ 33 - 1
cmd/compose/run.go

@@ -19,8 +19,10 @@ package compose
 import (
 	"context"
 	"fmt"
+	"os"
 	"strings"
 
+	"github.com/compose-spec/compose-go/v2/dotenv"
 	"github.com/compose-spec/compose-go/v2/format"
 	xprogress "github.com/moby/buildkit/util/progress/progressui"
 	"github.com/sirupsen/logrus"
@@ -44,6 +46,7 @@ type runOptions struct {
 	Service       string
 	Command       []string
 	environment   []string
+	envFiles      []string
 	Detach        bool
 	Remove        bool
 	noTty         bool
@@ -116,6 +119,29 @@ func (options runOptions) apply(project *types.Project) (*types.Project, error)
 	return project, nil
 }
 
+func (options runOptions) getEnvironment() (types.Mapping, error) {
+	environment := types.NewMappingWithEquals(options.environment).Resolve(os.LookupEnv).ToMapping()
+	for _, file := range options.envFiles {
+		f, err := os.Open(file)
+		if err != nil {
+			return nil, err
+		}
+		vars, err := dotenv.ParseWithLookup(f, func(k string) (string, bool) {
+			value, ok := environment[k]
+			return value, ok
+		})
+		if err != nil {
+			return nil, nil
+		}
+		for k, v := range vars {
+			if _, ok := environment[k]; !ok {
+				environment[k] = v
+			}
+		}
+	}
+	return environment, nil
+}
+
 func runCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
 	options := runOptions{
 		composeOptions: &composeOptions{
@@ -175,6 +201,7 @@ func runCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *
 	flags := cmd.Flags()
 	flags.BoolVarP(&options.Detach, "detach", "d", false, "Run container in background and print container ID")
 	flags.StringArrayVarP(&options.environment, "env", "e", []string{}, "Set environment variables")
+	flags.StringArrayVar(&options.envFiles, "env-from-file", []string{}, "Set environment variables from file")
 	flags.StringArrayVarP(&options.labels, "label", "l", []string{}, "Add or override a label")
 	flags.BoolVar(&options.Remove, "rm", false, "Automatically remove the container when it exits")
 	flags.BoolVarP(&options.noTty, "no-TTY", "T", !dockerCli.Out().IsTerminal(), "Disable pseudo-TTY allocation (default: auto-detected)")
@@ -264,6 +291,11 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
 		buildForRun = &bo
 	}
 
+	environment, err := options.getEnvironment()
+	if err != nil {
+		return err
+	}
+
 	// start container and attach to container streams
 	runOpts := api.RunOptions{
 		Build:             buildForRun,
@@ -278,7 +310,7 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
 		User:              options.user,
 		CapAdd:            options.capAdd.GetAll(),
 		CapDrop:           options.capDrop.GetAll(),
-		Environment:       options.environment,
+		Environment:       environment.Values(),
 		Entrypoint:        options.entrypointCmd,
 		Labels:            labels,
 		UseNetworkAliases: options.useAliases,

+ 1 - 0
docs/reference/compose_run.md

@@ -66,6 +66,7 @@ specified in the service configuration.
 | `--dry-run`             | `bool`        |          | Execute command in dry run mode                                                  |
 | `--entrypoint`          | `string`      |          | Override the entrypoint of the image                                             |
 | `-e`, `--env`           | `stringArray` |          | Set environment variables                                                        |
+| `--env-from-file`       | `stringArray` |          | Set environment variables from file                                              |
 | `-i`, `--interactive`   | `bool`        | `true`   | Keep STDIN open even if not attached                                             |
 | `-l`, `--label`         | `stringArray` |          | Add or override a label                                                          |
 | `--name`                | `string`      |          | Assign a name to the container                                                   |

+ 10 - 0
docs/reference/docker_compose_run.yaml

@@ -117,6 +117,16 @@ options:
       experimentalcli: false
       kubernetes: false
       swarm: false
+    - option: env-from-file
+      value_type: stringArray
+      default_value: '[]'
+      description: Set environment variables from file
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
     - option: interactive
       shorthand: i
       value_type: bool

+ 6 - 0
pkg/e2e/compose_run_test.go

@@ -178,4 +178,10 @@ func TestLocalComposeRun(t *testing.T) {
 		assert.Assert(t, strings.Contains(res.Combined(), "backend Pulling"), res.Combined())
 		assert.Assert(t, strings.Contains(res.Combined(), "backend Pulled"), res.Combined())
 	})
+
+	t.Run("compose run --env-from-file", func(t *testing.T) {
+		res := c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/compose.yaml", "run", "--env-from-file", "./fixtures/run-test/run.env",
+			"front", "env")
+		res.Assert(t, icmd.Expected{Out: "FOO=BAR"})
+	})
 }

+ 0 - 1
pkg/e2e/fixtures/run-test/compose.yaml

@@ -1,4 +1,3 @@
-version: '3.8'
 services:
   back:
     image: alpine

+ 1 - 0
pkg/e2e/fixtures/run-test/run.env

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