From 01d713986a09eb975c9da60fd1787b00be112566 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Tue, 19 Jul 2016 23:58:32 -0700 Subject: [PATCH] Add `--env-file` flag to `docker create service` This fix tries to address the issue in 24712 and add `--env-file` file to `docker create service`. Related documentation has been updated. An additional integration has been added. This fix fixes 24712. Signed-off-by: Yong Tang Upstream-commit: 1250d2afae8d0196f1a3d6c77c001f3e6c3f55a3 Component: cli --- components/cli/command/service/create.go | 1 + components/cli/command/service/opts.go | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/components/cli/command/service/create.go b/components/cli/command/service/create.go index bc5576b1ad..59e838ca8f 100644 --- a/components/cli/command/service/create.go +++ b/components/cli/command/service/create.go @@ -32,6 +32,7 @@ func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command { flags.VarP(&opts.labels, flagLabel, "l", "Service labels") flags.Var(&opts.containerLabels, flagContainerLabel, "Container labels") flags.VarP(&opts.env, flagEnv, "e", "Set environment variables") + flags.Var(&opts.envFile, flagEnvFile, "Read in a file of environment variables") flags.Var(&opts.mounts, flagMount, "Attach a mount to the service") flags.StringSliceVar(&opts.constraints, flagConstraint, []string{}, "Placement constraints") flags.StringSliceVar(&opts.networks, flagNetwork, []string{}, "Network attachments") diff --git a/components/cli/command/service/opts.go b/components/cli/command/service/opts.go index cf25b78273..87968fd1b4 100644 --- a/components/cli/command/service/opts.go +++ b/components/cli/command/service/opts.go @@ -395,6 +395,7 @@ type serviceOptions struct { image string args []string env opts.ListOpts + envFile opts.ListOpts workdir string user string groups []string @@ -422,6 +423,7 @@ func newServiceOptions() *serviceOptions { labels: opts.NewListOpts(runconfigopts.ValidateEnv), containerLabels: opts.NewListOpts(runconfigopts.ValidateEnv), env: opts.NewListOpts(runconfigopts.ValidateEnv), + envFile: opts.NewListOpts(nil), endpoint: endpointOptions{ ports: opts.NewListOpts(ValidatePort), }, @@ -432,6 +434,25 @@ func newServiceOptions() *serviceOptions { func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) { var service swarm.ServiceSpec + envVariables, err := runconfigopts.ReadKVStrings(opts.envFile.GetAll(), opts.env.GetAll()) + if err != nil { + return service, err + } + + currentEnv := make([]string, 0, len(envVariables)) + for _, env := range envVariables { // need to process each var, in order + k := strings.SplitN(env, "=", 2)[0] + for i, current := range currentEnv { // remove duplicates + if current == env { + continue // no update required, may hide this behind flag to preserve order of envVariables + } + if strings.HasPrefix(current, k+"=") { + currentEnv = append(currentEnv[:i], currentEnv[i+1:]...) + } + } + currentEnv = append(currentEnv, env) + } + service = swarm.ServiceSpec{ Annotations: swarm.Annotations{ Name: opts.name, @@ -441,7 +462,7 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) { ContainerSpec: swarm.ContainerSpec{ Image: opts.image, Args: opts.args, - Env: opts.env.GetAll(), + Env: currentEnv, Labels: runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()), Dir: opts.workdir, User: opts.user, @@ -532,6 +553,7 @@ const ( flagContainerLabelAdd = "container-label-add" flagEndpointMode = "endpoint-mode" flagEnv = "env" + flagEnvFile = "env-file" flagEnvRemove = "env-rm" flagEnvAdd = "env-add" flagGroupAdd = "group-add"