diff --git a/common/shell-local/communicator.go b/common/shell-local/communicator.go index 5532143c9..7664bc896 100644 --- a/common/shell-local/communicator.go +++ b/common/shell-local/communicator.go @@ -5,7 +5,6 @@ import ( "io" "os" "os/exec" - "runtime" "syscall" "github.com/hashicorp/packer/packer" @@ -17,22 +16,7 @@ type Communicator struct { func (c *Communicator) Start(cmd *packer.RemoteCmd) error { if len(c.ExecuteCommand) == 0 { - // Get default Execute Command - if runtime.GOOS == "windows" { - c.ExecuteCommand = []string{ - "cmd", - "/C", - "{{.Vars}}", - "{{.Command}}", - } - } else { - c.ExecuteCommand = []string{ - "/bin/sh", - "-c", - "{{.Vars}}", - "{{.Command}}", - } - } + return fmt.Errorf("Error launching command via shell-local communicator: No ExecuteCommand provided") } // Build the local command to execute diff --git a/common/shell-local/communicator_test.go b/common/shell-local/communicator_test.go index 903ab154d..9a8cb9057 100644 --- a/common/shell-local/communicator_test.go +++ b/common/shell-local/communicator_test.go @@ -20,13 +20,12 @@ func TestCommunicator(t *testing.T) { } c := &Communicator{ - ExecuteCommand: []string{"/bin/sh", "-c", "{{.Command}}"}, + ExecuteCommand: []string{"/bin/sh", "-c", "echo foo"}, } var buf bytes.Buffer cmd := &packer.RemoteCmd{ - Command: "echo foo", - Stdout: &buf, + Stdout: &buf, } if err := c.Start(cmd); err != nil { diff --git a/common/shell-local/config.go b/common/shell-local/config.go index a6a0a279d..dfd3623b9 100644 --- a/common/shell-local/config.go +++ b/common/shell-local/config.go @@ -58,10 +58,10 @@ func Decode(config *Config, raws ...interface{}) error { }, }, raws...) if err != nil { - return err + return fmt.Errorf("Error decoding config: %s, config is %#v, and raws is %#v", err, config, raws) } - return Validate(config) + return nil } func Validate(config *Config) error { @@ -98,7 +98,7 @@ func Validate(config *Config) error { } // Verify that the user has given us a command to run - if config.Command != "" && len(config.Inline) == 0 && + if config.Command == "" && len(config.Inline) == 0 && len(config.Scripts) == 0 && config.Script == "" { errs = packer.MultiErrorAppend(errs, errors.New("Command, Inline, Script and Scripts options cannot all be empty.")) diff --git a/post-processor/shell-local/post-processor.go b/post-processor/shell-local/post-processor.go index b1585a228..91bc5acc9 100644 --- a/post-processor/shell-local/post-processor.go +++ b/post-processor/shell-local/post-processor.go @@ -15,7 +15,7 @@ type ExecuteCommandTemplate struct { } func (p *PostProcessor) Configure(raws ...interface{}) error { - err := sl.Decode(&p.config, raws) + err := sl.Decode(&p.config, raws...) if err != nil { return err } diff --git a/post-processor/shell-local/post-processor_test.go b/post-processor/shell-local/post-processor_test.go index 7bdef1c32..caf4f5a42 100644 --- a/post-processor/shell-local/post-processor_test.go +++ b/post-processor/shell-local/post-processor_test.go @@ -28,20 +28,20 @@ func TestPostProcessor_Impl(t *testing.T) { func TestPostProcessorPrepare_Defaults(t *testing.T) { var p PostProcessor - config := testConfig() + raws := testConfig() - err := p.Configure(config) + err := p.Configure(raws) if err != nil { t.Fatalf("err: %s", err) } } func TestPostProcessorPrepare_InlineShebang(t *testing.T) { - config := testConfig() + raws := testConfig() - delete(config, "inline_shebang") + delete(raws, "inline_shebang") p := new(PostProcessor) - err := p.Configure(config) + err := p.Configure(raws) if err != nil { t.Fatalf("should not have error: %s", err) } @@ -51,9 +51,9 @@ func TestPostProcessorPrepare_InlineShebang(t *testing.T) { } // Test with a good one - config["inline_shebang"] = "foo" + raws["inline_shebang"] = "foo" p = new(PostProcessor) - err = p.Configure(config) + err = p.Configure(raws) if err != nil { t.Fatalf("should not have error: %s", err) } @@ -65,23 +65,23 @@ func TestPostProcessorPrepare_InlineShebang(t *testing.T) { func TestPostProcessorPrepare_InvalidKey(t *testing.T) { var p PostProcessor - config := testConfig() + raws := testConfig() // Add a random key - config["i_should_not_be_valid"] = true - err := p.Configure(config) + raws["i_should_not_be_valid"] = true + err := p.Configure(raws) if err == nil { t.Fatal("should have error") } } func TestPostProcessorPrepare_Script(t *testing.T) { - config := testConfig() - delete(config, "inline") + raws := testConfig() + delete(raws, "inline") - config["script"] = "/this/should/not/exist" + raws["script"] = "/this/should/not/exist" p := new(PostProcessor) - err := p.Configure(config) + err := p.Configure(raws) if err == nil { t.Fatal("should have error") } @@ -93,9 +93,9 @@ func TestPostProcessorPrepare_Script(t *testing.T) { } defer os.Remove(tf.Name()) - config["script"] = tf.Name() + raws["script"] = tf.Name() p = new(PostProcessor) - err = p.Configure(config) + err = p.Configure(raws) if err != nil { t.Fatalf("should not have error: %s", err) } @@ -103,13 +103,16 @@ func TestPostProcessorPrepare_Script(t *testing.T) { func TestPostProcessorPrepare_ScriptAndInline(t *testing.T) { var p PostProcessor - config := testConfig() + raws := testConfig() - delete(config, "inline") - delete(config, "script") - err := p.Configure(config) + // Error if no scripts/inline commands provided + delete(raws, "inline") + delete(raws, "script") + delete(raws, "command") + delete(raws, "scripts") + err := p.Configure(raws) if err == nil { - t.Fatal("should have error") + t.Fatalf("should error when no scripts/inline commands are provided: %#v", raws) } // Test with both @@ -119,9 +122,9 @@ func TestPostProcessorPrepare_ScriptAndInline(t *testing.T) { } defer os.Remove(tf.Name()) - config["inline"] = []interface{}{"foo"} - config["script"] = tf.Name() - err = p.Configure(config) + raws["inline"] = []interface{}{"foo"} + raws["script"] = tf.Name() + err = p.Configure(raws) if err == nil { t.Fatal("should have error") } @@ -129,7 +132,7 @@ func TestPostProcessorPrepare_ScriptAndInline(t *testing.T) { func TestPostProcessorPrepare_ScriptAndScripts(t *testing.T) { var p PostProcessor - config := testConfig() + raws := testConfig() // Test with both tf, err := ioutil.TempFile("", "packer") @@ -138,21 +141,21 @@ func TestPostProcessorPrepare_ScriptAndScripts(t *testing.T) { } defer os.Remove(tf.Name()) - config["inline"] = []interface{}{"foo"} - config["scripts"] = []string{tf.Name()} - err = p.Configure(config) + raws["inline"] = []interface{}{"foo"} + raws["scripts"] = []string{tf.Name()} + err = p.Configure(raws) if err == nil { t.Fatal("should have error") } } func TestPostProcessorPrepare_Scripts(t *testing.T) { - config := testConfig() - delete(config, "inline") + raws := testConfig() + delete(raws, "inline") - config["scripts"] = []string{} + raws["scripts"] = []string{} p := new(PostProcessor) - err := p.Configure(config) + err := p.Configure(raws) if err == nil { t.Fatal("should have error") } @@ -164,92 +167,55 @@ func TestPostProcessorPrepare_Scripts(t *testing.T) { } defer os.Remove(tf.Name()) - config["scripts"] = []string{tf.Name()} + raws["scripts"] = []string{tf.Name()} p = new(PostProcessor) - err = p.Configure(config) + err = p.Configure(raws) if err != nil { t.Fatalf("should not have error: %s", err) } } func TestPostProcessorPrepare_EnvironmentVars(t *testing.T) { - config := testConfig() + raws := testConfig() // Test with a bad case - config["environment_vars"] = []string{"badvar", "good=var"} + raws["environment_vars"] = []string{"badvar", "good=var"} p := new(PostProcessor) - err := p.Configure(config) + err := p.Configure(raws) if err == nil { t.Fatal("should have error") } // Test with a trickier case - config["environment_vars"] = []string{"=bad"} + raws["environment_vars"] = []string{"=bad"} p = new(PostProcessor) - err = p.Configure(config) + err = p.Configure(raws) if err == nil { t.Fatal("should have error") } // Test with a good case // Note: baz= is a real env variable, just empty - config["environment_vars"] = []string{"FOO=bar", "baz="} + raws["environment_vars"] = []string{"FOO=bar", "baz="} p = new(PostProcessor) - err = p.Configure(config) + err = p.Configure(raws) if err != nil { t.Fatalf("should not have error: %s", err) } // Test when the env variable value contains an equals sign - config["environment_vars"] = []string{"good=withequals=true"} + raws["environment_vars"] = []string{"good=withequals=true"} p = new(PostProcessor) - err = p.Configure(config) + err = p.Configure(raws) if err != nil { t.Fatalf("should not have error: %s", err) } // Test when the env variable value starts with an equals sign - config["environment_vars"] = []string{"good==true"} + raws["environment_vars"] = []string{"good==true"} p = new(PostProcessor) - err = p.Configure(config) + err = p.Configure(raws) if err != nil { t.Fatalf("should not have error: %s", err) } } - -func TestPostProcessor_createFlattenedEnvVars(t *testing.T) { - var flattenedEnvVars string - config := testConfig() - - userEnvVarTests := [][]string{ - {}, // No user env var - {"FOO=bar"}, // Single user env var - {"FOO=bar's"}, // User env var with single quote in value - {"FOO=bar", "BAZ=qux"}, // Multiple user env vars - {"FOO=bar=baz"}, // User env var with value containing equals - {"FOO==bar"}, // User env var with value starting with equals - } - expected := []string{ - `PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `, - `FOO='bar' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `, - `FOO='bar'"'"'s' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `, - `BAZ='qux' FOO='bar' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `, - `FOO='bar=baz' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `, - `FOO='=bar' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `, - } - - p := new(PostProcessor) - p.Configure(config) - - // Defaults provided by Packer - p.config.PackerBuildName = "vmware" - p.config.PackerBuilderType = "iso" - - for i, expectedValue := range expected { - p.config.Vars = userEnvVarTests[i] - flattenedEnvVars = p.createFlattenedEnvVars() - if flattenedEnvVars != expectedValue { - t.Fatalf("expected flattened env vars to be: %s, got %s.", expectedValue, flattenedEnvVars) - } - } -}