diff --git a/builder/amazon/chroot/run_local_commands.go b/builder/amazon/chroot/run_local_commands.go index 024a208f8..154d37a4f 100644 --- a/builder/amazon/chroot/run_local_commands.go +++ b/builder/amazon/chroot/run_local_commands.go @@ -3,8 +3,8 @@ package chroot import ( "fmt" + sl "github.com/hashicorp/packer/common/shell-local" "github.com/hashicorp/packer/packer" - "github.com/hashicorp/packer/post-processor/shell-local" "github.com/hashicorp/packer/template/interpolate" ) @@ -21,7 +21,10 @@ func RunLocalCommands(commands []string, wrappedCommand CommandWrapper, ctx inte } ui.Say(fmt.Sprintf("Executing command: %s", command)) - comm := &shell_local.Communicator{} + comm := &sl.Communicator{ + Ctx: ctx, + ExecuteCommand: []string{""}, + } cmd := &packer.RemoteCmd{Command: command} if err := cmd.StartWithUi(comm, ui); err != nil { return fmt.Errorf("Error executing command: %s", err) diff --git a/provisioner/shell-local/communicator.go b/common/shell-local/communicator.go similarity index 71% rename from provisioner/shell-local/communicator.go rename to common/shell-local/communicator.go index 2afbe1028..dc84b575a 100644 --- a/provisioner/shell-local/communicator.go +++ b/common/shell-local/communicator.go @@ -1,10 +1,11 @@ -package shell +package shell_local import ( "fmt" "io" "os" "os/exec" + "runtime" "syscall" "github.com/hashicorp/packer/packer" @@ -17,17 +18,34 @@ type Communicator struct { } func (c *Communicator) Start(cmd *packer.RemoteCmd) error { - // Render the template so that we know how to execute the command - c.Ctx.Data = &ExecuteCommandTemplate{ - Command: cmd.Command, - } - for i, field := range c.ExecuteCommand { - command, err := interpolate.Render(field, &c.Ctx) - if err != nil { - return fmt.Errorf("Error processing command: %s", err) + if len(c.ExecuteCommand) == 0 { + // Get default Execute Command + if runtime.GOOS == "windows" { + c.ExecuteCommand = []string{ + "cmd", + "/C", + "{{.Command}}", + } + } else { + c.ExecuteCommand = []string{ + "/bin/sh", + "-c", + "{{.Command}}", + } } + } else { + // Render the template so that we know how to execute the command + c.Ctx.Data = &ExecuteCommandTemplate{ + Command: cmd.Command, + } + for i, field := range c.ExecuteCommand { + command, err := interpolate.Render(field, &c.Ctx) + if err != nil { + return fmt.Errorf("Error processing command: %s", err) + } - c.ExecuteCommand[i] = command + c.ExecuteCommand[i] = command + } } // Build the local command to execute diff --git a/provisioner/shell-local/communicator_test.go b/common/shell-local/communicator_test.go similarity index 97% rename from provisioner/shell-local/communicator_test.go rename to common/shell-local/communicator_test.go index 8ebd4fa60..903ab154d 100644 --- a/provisioner/shell-local/communicator_test.go +++ b/common/shell-local/communicator_test.go @@ -1,4 +1,4 @@ -package shell +package shell_local import ( "bytes" diff --git a/post-processor/shell-local/communicator.go b/post-processor/shell-local/communicator.go deleted file mode 100644 index b0bfb008f..000000000 --- a/post-processor/shell-local/communicator.go +++ /dev/null @@ -1,63 +0,0 @@ -package shell_local - -import ( - "fmt" - "io" - "os" - "os/exec" - "syscall" - - "github.com/hashicorp/packer/packer" -) - -type Communicator struct{} - -func (c *Communicator) Start(cmd *packer.RemoteCmd) error { - localCmd := exec.Command("sh", "-c", cmd.Command) - localCmd.Stdin = cmd.Stdin - localCmd.Stdout = cmd.Stdout - localCmd.Stderr = cmd.Stderr - - // Start it. If it doesn't work, then error right away. - if err := localCmd.Start(); err != nil { - return err - } - - // We've started successfully. Start a goroutine to wait for - // it to complete and track exit status. - go func() { - var exitStatus int - err := localCmd.Wait() - if err != nil { - if exitErr, ok := err.(*exec.ExitError); ok { - exitStatus = 1 - - // There is no process-independent way to get the REAL - // exit status so we just try to go deeper. - if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { - exitStatus = status.ExitStatus() - } - } - } - - cmd.SetExited(exitStatus) - }() - - return nil -} - -func (c *Communicator) Upload(string, io.Reader, *os.FileInfo) error { - return fmt.Errorf("upload not supported") -} - -func (c *Communicator) UploadDir(string, string, []string) error { - return fmt.Errorf("uploadDir not supported") -} - -func (c *Communicator) Download(string, io.Writer) error { - return fmt.Errorf("download not supported") -} - -func (c *Communicator) DownloadDir(src string, dst string, exclude []string) error { - return fmt.Errorf("downloadDir not supported") -} diff --git a/post-processor/shell-local/communicator_test.go b/post-processor/shell-local/communicator_test.go deleted file mode 100644 index 025deec54..000000000 --- a/post-processor/shell-local/communicator_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package shell_local - -import ( - "bytes" - "runtime" - "strings" - "testing" - - "github.com/hashicorp/packer/packer" -) - -func TestCommunicator_impl(t *testing.T) { - var _ packer.Communicator = new(Communicator) -} - -func TestCommunicator(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("windows not supported for this test") - return - } - - c := &Communicator{} - - var buf bytes.Buffer - cmd := &packer.RemoteCmd{ - Command: "/bin/echo foo", - Stdout: &buf, - } - - if err := c.Start(cmd); err != nil { - t.Fatalf("err: %s", err) - } - - cmd.Wait() - - if cmd.ExitStatus != 0 { - t.Fatalf("err bad exit status: %d", cmd.ExitStatus) - } - - if strings.TrimSpace(buf.String()) != "foo" { - t.Fatalf("bad: %s", buf.String()) - } -} diff --git a/post-processor/shell-local/post-processor.go b/post-processor/shell-local/post-processor.go index c2bd2d5c0..d77086177 100644 --- a/post-processor/shell-local/post-processor.go +++ b/post-processor/shell-local/post-processor.go @@ -11,6 +11,7 @@ import ( "strings" "github.com/hashicorp/packer/common" + sl "github.com/hashicorp/packer/common/shell-local" "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/template/interpolate" @@ -178,7 +179,10 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac ui.Say(fmt.Sprintf("Post processing with local shell script: %s", script)) - comm := &Communicator{} + comm := &sl.Communicator{ + Ctx: p.config.ctx, + ExecuteCommand: []string{p.config.ExecuteCommand}, + } cmd := &packer.RemoteCmd{Command: command} diff --git a/provisioner/shell-local/provisioner.go b/provisioner/shell-local/provisioner.go index 3f8222c19..ecd59fa98 100644 --- a/provisioner/shell-local/provisioner.go +++ b/provisioner/shell-local/provisioner.go @@ -3,9 +3,9 @@ package shell import ( "errors" "fmt" - "runtime" "github.com/hashicorp/packer/common" + sl "github.com/hashicorp/packer/common/shell-local" "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/template/interpolate" @@ -41,33 +41,12 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return err } - if len(p.config.ExecuteCommand) == 0 { - if runtime.GOOS == "windows" { - p.config.ExecuteCommand = []string{ - "cmd", - "/C", - "{{.Command}}", - } - } else { - p.config.ExecuteCommand = []string{ - "/bin/sh", - "-c", - "{{.Command}}", - } - } - } - var errs *packer.MultiError if p.config.Command == "" { errs = packer.MultiErrorAppend(errs, errors.New("command must be specified")) } - if len(p.config.ExecuteCommand) == 0 { - errs = packer.MultiErrorAppend(errs, - errors.New("execute_command must not be empty")) - } - if errs != nil && len(errs.Errors) > 0 { return errs } @@ -77,7 +56,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { func (p *Provisioner) Provision(ui packer.Ui, _ packer.Communicator) error { // Make another communicator for local - comm := &Communicator{ + comm := &sl.Communicator{ Ctx: p.config.ctx, ExecuteCommand: p.config.ExecuteCommand, }