builder/docker: wait for tail to end when running remote command
This commit is contained in:
parent
c139aa3b71
commit
b267c3eb4a
|
@ -33,6 +33,8 @@ BUG FIXES:
|
||||||
* builder/amazon/all: More desctriptive error messages if Amazon only
|
* builder/amazon/all: More desctriptive error messages if Amazon only
|
||||||
sends an error code. [GH-1189]
|
sends an error code. [GH-1189]
|
||||||
* builder/docker: Remove the container during cleanup. [GH-1206]
|
* builder/docker: Remove the container during cleanup. [GH-1206]
|
||||||
|
* builder/docker: Fix case where not all output would show up from
|
||||||
|
provisioners.
|
||||||
* builder/googlecompute: add `disk_size` option. [GH-1397]
|
* builder/googlecompute: add `disk_size` option. [GH-1397]
|
||||||
* builder/openstack: Region is not required. [GH-1418]
|
* builder/openstack: Region is not required. [GH-1418]
|
||||||
* builder/parallels-iso: ISO not removed from VM after install [GH-1338]
|
* builder/parallels-iso: ISO not removed from VM after install [GH-1338]
|
||||||
|
|
|
@ -232,20 +232,42 @@ func (c *Communicator) run(cmd *exec.Cmd, remote *packer.RemoteCmd, stdin_w io.W
|
||||||
stdin_w.Write([]byte(remoteCmd + "\n"))
|
stdin_w.Write([]byte(remoteCmd + "\n"))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Start a goroutine to read all the lines out of the logs
|
// Start a goroutine to read all the lines out of the logs. These channels
|
||||||
|
// allow us to stop the go-routine and wait for it to be stopped.
|
||||||
|
stopTailCh := make(chan struct{})
|
||||||
|
doneCh := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
for line := range tail.Lines {
|
defer close(doneCh)
|
||||||
if remote.Stdout != nil {
|
|
||||||
remote.Stdout.Write([]byte(line.Text + "\n"))
|
for {
|
||||||
} else {
|
select {
|
||||||
log.Printf("Command stdout: %#v", line.Text)
|
case <-tail.Dead():
|
||||||
|
return
|
||||||
|
case line := <-tail.Lines:
|
||||||
|
if remote.Stdout != nil {
|
||||||
|
remote.Stdout.Write([]byte(line.Text + "\n"))
|
||||||
|
} else {
|
||||||
|
log.Printf("Command stdout: %#v", line.Text)
|
||||||
|
}
|
||||||
|
case <-time.After(2 * time.Second):
|
||||||
|
// If we're done, then return. Otherwise, keep grabbing
|
||||||
|
// data. This gives us a chance to flush all the lines
|
||||||
|
// out of the tailed file.
|
||||||
|
select {
|
||||||
|
case <-stopTailCh:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
var exitRaw []byte
|
||||||
|
var exitStatus int
|
||||||
|
var exitStatusRaw int64
|
||||||
err = cmd.Wait()
|
err = cmd.Wait()
|
||||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||||
exitStatus := 1
|
exitStatus = 1
|
||||||
|
|
||||||
// There is no process-independent way to get the REAL
|
// There is no process-independent way to get the REAL
|
||||||
// exit status so we just try to go deeper.
|
// exit status so we just try to go deeper.
|
||||||
|
@ -255,8 +277,7 @@ func (c *Communicator) run(cmd *exec.Cmd, remote *packer.RemoteCmd, stdin_w io.W
|
||||||
|
|
||||||
// Say that we ended, since if Docker itself failed, then
|
// Say that we ended, since if Docker itself failed, then
|
||||||
// the command must've not run, or so we assume
|
// the command must've not run, or so we assume
|
||||||
remote.SetExited(exitStatus)
|
goto REMOTE_EXIT
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the exit code to appear in our file...
|
// Wait for the exit code to appear in our file...
|
||||||
|
@ -271,21 +292,27 @@ func (c *Communicator) run(cmd *exec.Cmd, remote *packer.RemoteCmd, stdin_w io.W
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the exit code
|
// Read the exit code
|
||||||
exitRaw, err := ioutil.ReadFile(exitCodePath)
|
exitRaw, err = ioutil.ReadFile(exitCodePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error executing: %s", err)
|
log.Printf("Error executing: %s", err)
|
||||||
remote.SetExited(254)
|
exitStatus = 254
|
||||||
return
|
goto REMOTE_EXIT
|
||||||
}
|
}
|
||||||
|
|
||||||
exitStatus, err := strconv.ParseInt(string(bytes.TrimSpace(exitRaw)), 10, 0)
|
exitStatusRaw, err = strconv.ParseInt(string(bytes.TrimSpace(exitRaw)), 10, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error executing: %s", err)
|
log.Printf("Error executing: %s", err)
|
||||||
remote.SetExited(254)
|
exitStatus = 254
|
||||||
return
|
goto REMOTE_EXIT
|
||||||
}
|
}
|
||||||
|
exitStatus = int(exitStatusRaw)
|
||||||
log.Printf("Executed command exit status: %d", exitStatus)
|
log.Printf("Executed command exit status: %d", exitStatus)
|
||||||
|
|
||||||
// Finally, we're done
|
REMOTE_EXIT:
|
||||||
remote.SetExited(int(exitStatus))
|
// Wait for the tail to finish
|
||||||
|
close(stopTailCh)
|
||||||
|
<-doneCh
|
||||||
|
|
||||||
|
// Set the exit status which triggers waiters
|
||||||
|
remote.SetExited(exitStatus)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue