From 0cbb4ff30c9a4cdce4caed68703db16d045668c5 Mon Sep 17 00:00:00 2001 From: DanHam Date: Mon, 23 Jan 2017 10:10:14 +0000 Subject: [PATCH] provisioner/shell: Align gen of flattened env vars with powershell/win-shell * Move code to generate quoted flattened env vars to separate function * Fix: generate flattened env vars once per provisioner not once per script --- provisioner/shell/provisioner.go | 60 +++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/provisioner/shell/provisioner.go b/provisioner/shell/provisioner.go index c37f8df6b..f8a646d66 100644 --- a/provisioner/shell/provisioner.go +++ b/provisioner/shell/provisioner.go @@ -11,6 +11,7 @@ import ( "log" "math/rand" "os" + "sort" "strings" "time" @@ -167,17 +168,11 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { } // Do a check for bad environment variables, such as '=foo', 'foobar' - for idx, kv := range p.config.Vars { + for _, kv := range p.config.Vars { vs := strings.SplitN(kv, "=", 2) if len(vs) != 2 || vs[0] == "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Environment variable not in format 'key=value': %s", kv)) - } else { - // Replace single quotes so they parse - vs[1] = strings.Replace(vs[1], "'", `'"'"'`, -1) - - // Single quote env var values - p.config.Vars[idx] = fmt.Sprintf("%s='%s'", vs[0], vs[1]) } } @@ -228,16 +223,8 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { tf.Close() } - // Build our variables up by adding in the build name and builder type - envVars := make([]string, len(p.config.Vars)+2) - envVars[0] = fmt.Sprintf("PACKER_BUILD_NAME='%s'", p.config.PackerBuildName) - envVars[1] = fmt.Sprintf("PACKER_BUILDER_TYPE='%s'", p.config.PackerBuilderType) - - copy(envVars[2:], p.config.Vars) - httpAddr := common.GetHTTPAddr() - if httpAddr != "" { - envVars = append(envVars, fmt.Sprintf("PACKER_HTTP_ADDR=%s", common.GetHTTPAddr())) - } + // Create environment variables to set before executing the command + flattenedEnvVars := p.createFlattenedEnvVars() for _, path := range scripts { ui.Say(fmt.Sprintf("Provisioning with shell script: %s", path)) @@ -249,12 +236,9 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { } defer f.Close() - // Flatten the environment variables - flattendVars := strings.Join(envVars, " ") - // Compile the command p.config.ctx.Data = &ExecuteCommandTemplate{ - Vars: flattendVars, + Vars: flattenedEnvVars, Path: p.config.RemotePath, } command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx) @@ -377,3 +361,37 @@ func (p *Provisioner) retryable(f func() error) error { } } } + +func (p *Provisioner) createFlattenedEnvVars() (flattened string) { + flattened = "" + envVars := make(map[string]string) + + // Always available Packer provided env vars + envVars["PACKER_BUILD_NAME"] = fmt.Sprintf("%s", p.config.PackerBuildName) + envVars["PACKER_BUILDER_TYPE"] = fmt.Sprintf("%s", p.config.PackerBuilderType) + httpAddr := common.GetHTTPAddr() + if httpAddr != "" { + envVars["PACKER_HTTP_ADDR"] = fmt.Sprintf("%s", httpAddr) + } + + // Split vars into key/value components + for _, envVar := range p.config.Vars { + keyValue := strings.SplitN(envVar, "=", 2) + // Store pair, replacing any single quotes in value so they parse + // correctly with required environment variable format + envVars[keyValue[0]] = strings.Replace(keyValue[1], "'", `'"'"'`, -1) + } + + // Create a list of env var keys in sorted order + var keys []string + for k := range envVars { + keys = append(keys, k) + } + sort.Strings(keys) + + // Re-assemble vars surrounding value with single quotes and flatten + for _, key := range keys { + flattened += fmt.Sprintf("%s='%s' ", key, envVars[key]) + } + return +}