From cd51ac92bdf1ce0a1245f5b4565995631512ba64 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Sun, 16 Feb 2014 19:24:22 -0500 Subject: [PATCH 01/10] support for `docker run` environment variables file Docker-DCO-1.1-Signed-off-by: Vincent Batts (github: vbatts) --- docs/sources/reference/commandline/cli.rst | 12 ++++++ pkg/opts/envfile.go | 44 ++++++++++++++++++++++ runconfig/parse.go | 14 ++++++- 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 pkg/opts/envfile.go diff --git a/docs/sources/reference/commandline/cli.rst b/docs/sources/reference/commandline/cli.rst index 3d2aac5233..6a473ec461 100644 --- a/docs/sources/reference/commandline/cli.rst +++ b/docs/sources/reference/commandline/cli.rst @@ -1152,6 +1152,7 @@ image is removed. --cidfile="": Write the container ID to the file -d, --detach=false: Detached mode: Run container in the background, print new container id -e, --env=[]: Set environment variables + --envfile="": Read in a line delimited file of ENV variables -h, --hostname="": Container host name -i, --interactive=false: Keep stdin open even if not attached --privileged=false: Give extended privileges to this container @@ -1284,6 +1285,17 @@ This exposes port ``80`` of the container for use within a link without publishing the port to the host system's interfaces. :ref:`port_redirection` explains in detail how to manipulate ports in Docker. +.. code-block:: bash + + $ sudo docker run -e MYVAR1 --env MYVAR2=foo --envfile ./env.list ubuntu bash + +This sets environmental variables to the container. For illustration all three +flags are shown here. Where -e and --env can be repeated, take an environment +variable and value, or if no "=" is provided, then that variable's current +value is passed through (i.e. $MYVAR1 from the host is set to $MYVAR1 in the +container). The --envfile flag takes a filename as an argument and expects each +line to be a VAR=VAL format. + .. code-block:: bash $ sudo docker run --name console -t -i ubuntu bash diff --git a/pkg/opts/envfile.go b/pkg/opts/envfile.go new file mode 100644 index 0000000000..004c320803 --- /dev/null +++ b/pkg/opts/envfile.go @@ -0,0 +1,44 @@ +package opts + +import ( + "bufio" + "bytes" + "io" + "os" +) + +/* +Read in a line delimited file with environment variables enumerated +*/ +func ParseEnvFile(filename string) ([]string, error) { + fh, err := os.Open(filename) + if err != nil { + return []string{}, err + } + var ( + lines []string = []string{} + line, chunk []byte + ) + reader := bufio.NewReader(fh) + line, isPrefix, err := reader.ReadLine() + + for err == nil { + if isPrefix { + chunk = append(chunk, line...) + } else if !isPrefix && len(chunk) > 0 { + line = chunk + chunk = []byte{} + } else { + chunk = []byte{} + } + + if !isPrefix && len(line) > 0 && bytes.Contains(line, []byte("=")) { + lines = append(lines, string(line)) + } + line, isPrefix, err = reader.ReadLine() + } + if err != nil && err != io.EOF { + return []string{}, err + } + return lines, nil +} diff --git a/runconfig/parse.go b/runconfig/parse.go index 43aecdb753..aa1ed6d174 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -68,6 +68,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container") flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)") flLabelOptions = cmd.String([]string{"Z", "-label"}, "", "Options to pass to underlying labeling system") + flEnvFile = cmd.String([]string{"#envfile", "-envfile"}, "", "Read in a line delimited file of ENV variables") // For documentation purpose _ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)") @@ -199,6 +200,17 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf } } + // collect all the environment variables for the container + envVariables := []string{} + envVariables = append(envVariables, flEnv.GetAll()...) + parsedVars, err := opts.ParseEnvFile(*flEnvFile) + if err != nil { + return nil, nil, cmd, err + } + envVariables = append(envVariables, parsedVars...) + // boo, there's no debug output for docker run + //utils.Debugf("Environment variables for the container: %#v", envVariables) + config := &Config{ Hostname: hostname, Domainname: domainname, @@ -213,7 +225,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf AttachStdin: flAttach.Get("stdin"), AttachStdout: flAttach.Get("stdout"), AttachStderr: flAttach.Get("stderr"), - Env: flEnv.GetAll(), + Env: envVariables, Cmd: runCmd, Dns: flDns.GetAll(), DnsSearch: flDnsSearch.GetAll(), From bfaa917a966fab1e2c92e70617320957a8d8b43b Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 18 Feb 2014 14:22:46 -0500 Subject: [PATCH 02/10] pkg/opts: Close the file handle Docker-DCO-1.1-Signed-off-by: Vincent Batts (github: vbatts) --- pkg/opts/envfile.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/opts/envfile.go b/pkg/opts/envfile.go index 004c320803..65495a1585 100644 --- a/pkg/opts/envfile.go +++ b/pkg/opts/envfile.go @@ -15,6 +15,8 @@ func ParseEnvFile(filename string) ([]string, error) { if err != nil { return []string{}, err } + defer fh.Close() + var ( lines []string = []string{} line, chunk []byte From 586e6c5eb9cd21a95d4bbba051249c4b05b2011e Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 18 Feb 2014 15:41:28 -0500 Subject: [PATCH 03/10] --env-file instead of --envfile Docker-DCO-1.1-Signed-off-by: Vincent Batts (github: vbatts) --- docs/sources/reference/commandline/cli.rst | 2 +- runconfig/parse.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sources/reference/commandline/cli.rst b/docs/sources/reference/commandline/cli.rst index 6a473ec461..d8cf5965da 100644 --- a/docs/sources/reference/commandline/cli.rst +++ b/docs/sources/reference/commandline/cli.rst @@ -1152,7 +1152,7 @@ image is removed. --cidfile="": Write the container ID to the file -d, --detach=false: Detached mode: Run container in the background, print new container id -e, --env=[]: Set environment variables - --envfile="": Read in a line delimited file of ENV variables + --env-file="": Read in a line delimited file of ENV variables -h, --hostname="": Container host name -i, --interactive=false: Keep stdin open even if not attached --privileged=false: Give extended privileges to this container diff --git a/runconfig/parse.go b/runconfig/parse.go index aa1ed6d174..6ebe9f2bc3 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -68,7 +68,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container") flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)") flLabelOptions = cmd.String([]string{"Z", "-label"}, "", "Options to pass to underlying labeling system") - flEnvFile = cmd.String([]string{"#envfile", "-envfile"}, "", "Read in a line delimited file of ENV variables") + flEnvFile = cmd.String([]string{"#env-file", "-env-file"}, "", "Read in a line delimited file of ENV variables") // For documentation purpose _ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)") From 4e0014f582617960bad513518d292b64da866f73 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Thu, 20 Feb 2014 15:34:45 -0500 Subject: [PATCH 04/10] go fmt Docker-DCO-1.1-Signed-off-by: Vincent Batts (github: vbatts) --- pkg/opts/envfile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/opts/envfile.go b/pkg/opts/envfile.go index 65495a1585..7c69f5d799 100644 --- a/pkg/opts/envfile.go +++ b/pkg/opts/envfile.go @@ -15,7 +15,7 @@ func ParseEnvFile(filename string) ([]string, error) { if err != nil { return []string{}, err } - defer fh.Close() + defer fh.Close() var ( lines []string = []string{} From bcba5246f993a74eece36aa4b25df5b5e486e15b Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Wed, 26 Feb 2014 16:05:25 -0500 Subject: [PATCH 05/10] Fixing doc references to --env-file Docker-DCO-1.1-Signed-off-by: Vincent Batts (github: vbatts) --- docs/sources/reference/commandline/cli.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sources/reference/commandline/cli.rst b/docs/sources/reference/commandline/cli.rst index d8cf5965da..4e697766bc 100644 --- a/docs/sources/reference/commandline/cli.rst +++ b/docs/sources/reference/commandline/cli.rst @@ -1287,13 +1287,13 @@ explains in detail how to manipulate ports in Docker. .. code-block:: bash - $ sudo docker run -e MYVAR1 --env MYVAR2=foo --envfile ./env.list ubuntu bash + $ sudo docker run -e MYVAR1 --env MYVAR2=foo --env-file ./env.list ubuntu bash This sets environmental variables to the container. For illustration all three flags are shown here. Where -e and --env can be repeated, take an environment variable and value, or if no "=" is provided, then that variable's current value is passed through (i.e. $MYVAR1 from the host is set to $MYVAR1 in the -container). The --envfile flag takes a filename as an argument and expects each +container). The --env-file flag takes a filename as an argument and expects each line to be a VAR=VAL format. .. code-block:: bash From acf5289dddfbbd69e19714f53575eb5088c618f7 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Thu, 6 Mar 2014 12:55:47 -0500 Subject: [PATCH 06/10] make the --env-file accept multiple flags Docker-DCO-1.1-Signed-off-by: Vincent Batts (github: vbatts) --- runconfig/parse.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/runconfig/parse.go b/runconfig/parse.go index 6ebe9f2bc3..e6e8b120d8 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -52,6 +52,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf flVolumesFrom opts.ListOpts flLxcOpts opts.ListOpts flDriverOpts opts.ListOpts + flEnvFile opts.ListOpts flAutoRemove = cmd.Bool([]string{"#rm", "-rm"}, false, "Automatically remove the container when it exits (incompatible with -d)") flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: Run container in the background, print new container id") @@ -68,7 +69,6 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container") flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)") flLabelOptions = cmd.String([]string{"Z", "-label"}, "", "Options to pass to underlying labeling system") - flEnvFile = cmd.String([]string{"#env-file", "-env-file"}, "", "Read in a line delimited file of ENV variables") // For documentation purpose _ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)") @@ -79,6 +79,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)") cmd.Var(&flLinks, []string{"#link", "-link"}, "Add link to another container (name:alias)") cmd.Var(&flEnv, []string{"e", "-env"}, "Set environment variables") + cmd.Var(&flEnvFile, []string{"#env-file", "-env-file"}, "Read in a line delimited file of ENV variables") cmd.Var(&flPublish, []string{"p", "-publish"}, fmt.Sprintf("Publish a container's port to the host (format: %s) (use 'docker port' to see the actual mapping)", nat.PortSpecTemplateFormat)) cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port from the container without publishing it to your host") @@ -203,11 +204,13 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf // collect all the environment variables for the container envVariables := []string{} envVariables = append(envVariables, flEnv.GetAll()...) - parsedVars, err := opts.ParseEnvFile(*flEnvFile) - if err != nil { - return nil, nil, cmd, err + for _, ef := range flEnvFile.GetAll() { + parsedVars, err := opts.ParseEnvFile(ef) + if err != nil { + return nil, nil, cmd, err + } + envVariables = append(envVariables, parsedVars...) } - envVariables = append(envVariables, parsedVars...) // boo, there's no debug output for docker run //utils.Debugf("Environment variables for the container: %#v", envVariables) From 33dde1f7288781a3a36951309f963e6040a1a0f5 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Thu, 6 Mar 2014 17:49:47 -0500 Subject: [PATCH 07/10] env-file: update functionality and docs Multiple flags allowed. Order prescribed. Examples provided. Multiline accounted for. Docker-DCO-1.1-Signed-off-by: Vincent Batts (github: vbatts) --- docs/sources/reference/commandline/cli.rst | 47 +++++++++++++++++++--- pkg/opts/envfile.go | 41 ++++++++----------- runconfig/parse.go | 3 +- 3 files changed, 59 insertions(+), 32 deletions(-) diff --git a/docs/sources/reference/commandline/cli.rst b/docs/sources/reference/commandline/cli.rst index 4e697766bc..989ea38798 100644 --- a/docs/sources/reference/commandline/cli.rst +++ b/docs/sources/reference/commandline/cli.rst @@ -1289,12 +1289,47 @@ explains in detail how to manipulate ports in Docker. $ sudo docker run -e MYVAR1 --env MYVAR2=foo --env-file ./env.list ubuntu bash -This sets environmental variables to the container. For illustration all three -flags are shown here. Where -e and --env can be repeated, take an environment -variable and value, or if no "=" is provided, then that variable's current -value is passed through (i.e. $MYVAR1 from the host is set to $MYVAR1 in the -container). The --env-file flag takes a filename as an argument and expects each -line to be a VAR=VAL format. +This sets environmental variables in the container. For illustration all three +flags are shown here. Where ``-e``, ``--env`` take an environment variable and +value, or if no "=" is provided, then that variable's current value is passed +through (i.e. $MYVAR1 from the host is set to $MYVAR1 in the container). All +three flags, ``-e``, ``--env`` and ``--env-file`` can be repeated. + +Regardless of the order of these three flags, the ``--env-file`` are processed +first, and then ``-e``/``--env`` flags. So that they can override VAR as needed. + +.. code-block:: bash + + $ cat ./env.list + TEST_FOO=BAR + $ sudo docker run --env TEST_FOO="This is a test" --env-file ./env.list busybox env | grep TEST_FOO + TEST_FOO=This is a test + +The ``--env-file`` flag takes a filename as an argument and expects each line +to be in the VAR=VAL format. The VAL is Unquoted, so if you need a multi-line +value, then use `\n` escape characters inside of a double quoted VAL. Single +quotes are literal. An example of a file passed with ``--env-file`` + +.. code-block:: bash + + $ cat ./env.list + TEST_FOO=BAR + TEST_APP_DEST_HOST=10.10.0.127 + TEST_APP_DEST_PORT=8888 + TEST_SOME_MULTILINE_VAR="this is first line\nthis is second line" + TEST_SOME_LITERAL_VAR='this\nwill\nall\nbe\none\nline' + $ sudo docker run --env-file ./env.list busybox env + HOME=/ + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + HOSTNAME=215d54a814bc + TEST_FOO=BAR + TEST_APP_DEST_HOST=10.10.0.127 + TEST_APP_DEST_PORT=8888 + TEST_SOME_MULTILINE_VAR=this is first line + this is second line + TEST_SOME_LITERAL_VAR='this\nwill\nall\nbe\none\nline' + container=lxc + .. code-block:: bash diff --git a/pkg/opts/envfile.go b/pkg/opts/envfile.go index 7c69f5d799..d9afdd952c 100644 --- a/pkg/opts/envfile.go +++ b/pkg/opts/envfile.go @@ -2,9 +2,10 @@ package opts import ( "bufio" - "bytes" - "io" + "fmt" "os" + "strconv" + "strings" ) /* @@ -17,30 +18,20 @@ func ParseEnvFile(filename string) ([]string, error) { } defer fh.Close() - var ( - lines []string = []string{} - line, chunk []byte - ) - reader := bufio.NewReader(fh) - line, isPrefix, err := reader.ReadLine() - - for err == nil { - if isPrefix { - chunk = append(chunk, line...) - } else if !isPrefix && len(chunk) > 0 { - line = chunk - chunk = []byte{} - } else { - chunk = []byte{} + lines := []string{} + scanner := bufio.NewScanner(fh) + for scanner.Scan() { + line := scanner.Text() + // line is not empty, and not starting with '#' + if len(line) > 0 && !strings.HasPrefix(line, "#") && strings.Contains(line, "=") { + data := strings.SplitN(line, "=", 2) + key := data[0] + val := data[1] + if str, err := strconv.Unquote(data[1]); err == nil { + val = str + } + lines = append(lines, fmt.Sprintf("%s=%s", key, val)) } - - if !isPrefix && len(line) > 0 && bytes.Contains(line, []byte("=")) { - lines = append(lines, string(line)) - } - line, isPrefix, err = reader.ReadLine() - } - if err != nil && err != io.EOF { - return []string{}, err } return lines, nil } diff --git a/runconfig/parse.go b/runconfig/parse.go index e6e8b120d8..d3e32bc2de 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -203,7 +203,6 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf // collect all the environment variables for the container envVariables := []string{} - envVariables = append(envVariables, flEnv.GetAll()...) for _, ef := range flEnvFile.GetAll() { parsedVars, err := opts.ParseEnvFile(ef) if err != nil { @@ -211,6 +210,8 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf } envVariables = append(envVariables, parsedVars...) } + // parse the '-e' and '--env' after, to allow override + envVariables = append(envVariables, flEnv.GetAll()...) // boo, there's no debug output for docker run //utils.Debugf("Environment variables for the container: %#v", envVariables) From d9c257732e435cecdcc1ec8452f35e7614e4713f Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Fri, 7 Mar 2014 16:18:42 -0500 Subject: [PATCH 08/10] env-file: remove the unneeded deprecation markup Docker-DCO-1.1-Signed-off-by: Vincent Batts (github: vbatts) --- runconfig/parse.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runconfig/parse.go b/runconfig/parse.go index d3e32bc2de..db4ac351a9 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -79,7 +79,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)") cmd.Var(&flLinks, []string{"#link", "-link"}, "Add link to another container (name:alias)") cmd.Var(&flEnv, []string{"e", "-env"}, "Set environment variables") - cmd.Var(&flEnvFile, []string{"#env-file", "-env-file"}, "Read in a line delimited file of ENV variables") + cmd.Var(&flEnvFile, []string{"-env-file"}, "Read in a line delimited file of ENV variables") cmd.Var(&flPublish, []string{"p", "-publish"}, fmt.Sprintf("Publish a container's port to the host (format: %s) (use 'docker port' to see the actual mapping)", nat.PortSpecTemplateFormat)) cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port from the container without publishing it to your host") From ff4ac7441ba582c8c339b25b400c6756d9646ff1 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 11 Mar 2014 16:22:58 -0400 Subject: [PATCH 09/10] --env-file: simple line-delimited match dock functionality, and not try to achieve shell-sourcing compatibility Docker-DCO-1.1-Signed-off-by: Vincent Batts (github: vbatts) --- docs/sources/reference/commandline/cli.rst | 26 ++++++++++++---------- {pkg/opts => opts}/envfile.go | 14 +++++------- 2 files changed, 20 insertions(+), 20 deletions(-) rename {pkg/opts => opts}/envfile.go (60%) diff --git a/docs/sources/reference/commandline/cli.rst b/docs/sources/reference/commandline/cli.rst index 989ea38798..0c9db138c2 100644 --- a/docs/sources/reference/commandline/cli.rst +++ b/docs/sources/reference/commandline/cli.rst @@ -1296,7 +1296,8 @@ through (i.e. $MYVAR1 from the host is set to $MYVAR1 in the container). All three flags, ``-e``, ``--env`` and ``--env-file`` can be repeated. Regardless of the order of these three flags, the ``--env-file`` are processed -first, and then ``-e``/``--env`` flags. So that they can override VAR as needed. +first, and then ``-e``/``--env`` flags. This way, the ``-e`` or ``--env`` will +override variables as needed. .. code-block:: bash @@ -1306,29 +1307,30 @@ first, and then ``-e``/``--env`` flags. So that they can override VAR as needed. TEST_FOO=This is a test The ``--env-file`` flag takes a filename as an argument and expects each line -to be in the VAR=VAL format. The VAL is Unquoted, so if you need a multi-line -value, then use `\n` escape characters inside of a double quoted VAL. Single -quotes are literal. An example of a file passed with ``--env-file`` +to be in the VAR=VAL format, mimicking the argument passed to ``--env``. +Comment lines need only be prefixed with ``#`` + +An example of a file passed with ``--env-file`` .. code-block:: bash $ cat ./env.list TEST_FOO=BAR + + # this is a comment TEST_APP_DEST_HOST=10.10.0.127 TEST_APP_DEST_PORT=8888 - TEST_SOME_MULTILINE_VAR="this is first line\nthis is second line" - TEST_SOME_LITERAL_VAR='this\nwill\nall\nbe\none\nline' - $ sudo docker run --env-file ./env.list busybox env + + # pass through this variable from the caller + TEST_PASSTHROUGH + $ sudo TEST_PASSTHROUGH=howdy docker run --env-file ./env.list busybox env HOME=/ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - HOSTNAME=215d54a814bc + HOSTNAME=5198e0745561 TEST_FOO=BAR TEST_APP_DEST_HOST=10.10.0.127 TEST_APP_DEST_PORT=8888 - TEST_SOME_MULTILINE_VAR=this is first line - this is second line - TEST_SOME_LITERAL_VAR='this\nwill\nall\nbe\none\nline' - container=lxc + TEST_PASSTHROUGH=howdy .. code-block:: bash diff --git a/pkg/opts/envfile.go b/opts/envfile.go similarity index 60% rename from pkg/opts/envfile.go rename to opts/envfile.go index d9afdd952c..99a713e761 100644 --- a/pkg/opts/envfile.go +++ b/opts/envfile.go @@ -4,7 +4,6 @@ import ( "bufio" "fmt" "os" - "strconv" "strings" ) @@ -23,14 +22,13 @@ func ParseEnvFile(filename string) ([]string, error) { for scanner.Scan() { line := scanner.Text() // line is not empty, and not starting with '#' - if len(line) > 0 && !strings.HasPrefix(line, "#") && strings.Contains(line, "=") { - data := strings.SplitN(line, "=", 2) - key := data[0] - val := data[1] - if str, err := strconv.Unquote(data[1]); err == nil { - val = str + if len(line) > 0 && !strings.HasPrefix(line, "#") { + if strings.Contains(line, "=") { + data := strings.SplitN(line, "=", 2) + lines = append(lines, fmt.Sprintf("%s=%s", data[0], data[1])) + } else { + lines = append(lines, fmt.Sprintf("%s=%s", line, os.Getenv(line))) } - lines = append(lines, fmt.Sprintf("%s=%s", key, val)) } } return lines, nil From 500c8ba4b66c35cf2c29aeb81a9392cc406835a4 Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Mon, 17 Mar 2014 17:11:27 -0400 Subject: [PATCH 10/10] env-file: variable behavior trim the front of variables. Error if there are other spaces present. Leave the value alone. Docker-DCO-1.1-Signed-off-by: Vincent Batts (github: vbatts) --- opts/envfile.go | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/opts/envfile.go b/opts/envfile.go index 99a713e761..19ee8955f9 100644 --- a/opts/envfile.go +++ b/opts/envfile.go @@ -25,11 +25,30 @@ func ParseEnvFile(filename string) ([]string, error) { if len(line) > 0 && !strings.HasPrefix(line, "#") { if strings.Contains(line, "=") { data := strings.SplitN(line, "=", 2) - lines = append(lines, fmt.Sprintf("%s=%s", data[0], data[1])) + + // trim the front of a variable, but nothing else + variable := strings.TrimLeft(data[0], whiteSpaces) + if strings.ContainsAny(variable, whiteSpaces) { + return []string{}, ErrBadEnvVariable{fmt.Sprintf("variable '%s' has white spaces", variable)} + } + + // pass the value through, no trimming + lines = append(lines, fmt.Sprintf("%s=%s", variable, data[1])) } else { - lines = append(lines, fmt.Sprintf("%s=%s", line, os.Getenv(line))) + // if only a pass-through variable is given, clean it up. + lines = append(lines, fmt.Sprintf("%s=%s", strings.TrimSpace(line), os.Getenv(line))) } } } return lines, nil } + +var whiteSpaces = " \t" + +type ErrBadEnvVariable struct { + msg string +} + +func (e ErrBadEnvVariable) Error() string { + return fmt.Sprintf("poorly formatted environment: %s", e.msg) +}