diff --git a/builtin/provisioners/local-exec/resource_provisioner.go b/builtin/provisioners/local-exec/resource_provisioner.go index 544dabe86..88e5e0045 100644 --- a/builtin/provisioners/local-exec/resource_provisioner.go +++ b/builtin/provisioners/local-exec/resource_provisioner.go @@ -2,12 +2,14 @@ package localexec import ( "fmt" + "io" "os/exec" "runtime" "github.com/armon/circbuf" "github.com/hashicorp/terraform/helper/config" "github.com/hashicorp/terraform/terraform" + "github.com/mitchellh/go-linereader" ) const ( @@ -44,17 +46,35 @@ func (p *ResourceProvisioner) Apply( flag = "-c" } + // Setup the reader that will read the lines from the command + pr, pw := io.Pipe() + copyDoneCh := make(chan struct{}) + go p.copyOutput(o, pr, copyDoneCh) + // Setup the command cmd := exec.Command(shell, flag, command) output, _ := circbuf.NewBuffer(maxBufSize) - cmd.Stderr = output - cmd.Stdout = output + cmd.Stderr = io.MultiWriter(output, pw) + cmd.Stdout = io.MultiWriter(output, pw) + + // Output what we're about to run + o.Output(fmt.Sprintf( + "Executing: %s %s \"%s\"", + shell, flag, command)) // Run the command to completion - if err := cmd.Run(); err != nil { + err := cmd.Run() + + // Close the write-end of the pipe so that the goroutine mirroring output + // ends properly. + pw.Close() + <-copyDoneCh + + if err != nil { return fmt.Errorf("Error running command '%s': %v. Output: %s", command, err, output.Bytes()) } + return nil } @@ -64,3 +84,12 @@ func (p *ResourceProvisioner) Validate(c *terraform.ResourceConfig) ([]string, [ } return validator.Validate(c) } + +func (p *ResourceProvisioner) copyOutput( + o terraform.UIOutput, r io.Reader, doneCh chan<- struct{}) { + defer close(doneCh) + lr := linereader.New(r) + for line := range lr.Ch { + o.Output(line) + } +}