Merge pull request #8607 from hashicorp/fix_vagrant_crash

Fix a crash in the vagrant driver
This commit is contained in:
Megan Marsh 2020-01-15 13:33:23 -08:00 committed by GitHub
commit ecf0e5794a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 40 deletions

View File

@ -1,6 +1,7 @@
package vagrant package vagrant
import ( import (
"bufio"
"bytes" "bytes"
"fmt" "fmt"
"log" "log"
@ -8,7 +9,6 @@ import (
"os/exec" "os/exec"
"regexp" "regexp"
"strings" "strings"
"time"
"github.com/hashicorp/go-version" "github.com/hashicorp/go-version"
) )
@ -190,16 +190,47 @@ func (d *Vagrant_2_2_Driver) Version() (string, error) {
return version, nil return version, nil
} }
func (d *Vagrant_2_2_Driver) vagrantCmd(args ...string) (string, string, error) { // Copied and modified from Bufio; this will return data that contains a
var stdout, stderr bytes.Buffer // carriage return, not just data that contains a newline.
// This allows us to stream progress output from vagrant that would otherwise
// be smothered. It is a bit noisy, but probably prefereable to suppressing
// the output in a way that looks like Packer has hung.
func ScanLinesInclCR(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
if i := bytes.IndexByte(data, '\n'); i >= 0 {
// We have a full newline-terminated line.
return i + 1, data[0:i], nil
}
if i := bytes.IndexByte(data, '\r'); i >= 0 {
// We have a CR-terminated line.
return i + 1, data[0:i], nil
}
// If we're at EOF, we have a final, non-terminated line. Return it.
if atEOF {
return len(data), data, nil
}
// Request more data.
return 0, nil, nil
}
func (d *Vagrant_2_2_Driver) vagrantCmd(args ...string) (string, string, error) {
log.Printf("Calling Vagrant CLI: %#v", args) log.Printf("Calling Vagrant CLI: %#v", args)
cmd := exec.Command(d.vagrantBinary, args...) cmd := exec.Command(d.vagrantBinary, args...)
cmd.Env = append(os.Environ(), fmt.Sprintf("VAGRANT_CWD=%s", d.VagrantCWD)) cmd.Env = append(os.Environ(), fmt.Sprintf("VAGRANT_CWD=%s", d.VagrantCWD))
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Start() stderr, err := cmd.StderrPipe()
if err != nil {
log.Printf("error getting err pipe")
}
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Printf("error getting out pipe")
}
err = cmd.Start()
if err != nil { if err != nil {
return "", "", fmt.Errorf("Error starting vagrant command with args: %q", return "", "", fmt.Errorf("Error starting vagrant command with args: %q",
strings.Join(args, " ")) strings.Join(args, " "))
@ -208,43 +239,24 @@ func (d *Vagrant_2_2_Driver) vagrantCmd(args ...string) (string, string, error)
stdoutString := "" stdoutString := ""
stderrString := "" stderrString := ""
donech := make(chan bool) scanOut := bufio.NewScanner(stdout)
scanOut.Split(ScanLinesInclCR)
scanErr := bufio.NewScanner(stderr)
scanErr.Split(ScanLinesInclCR)
go func() { go func() {
for { for scanErr.Scan() {
select { line := scanErr.Text()
case <-donech:
line := stdout.String()
if line != "" {
log.Printf("[vagrant driver] stdout: %s", line)
}
stdoutString += line
line = stderr.String()
if line != "" {
log.Printf("[vagrant driver] stderr: %s", line) log.Printf("[vagrant driver] stderr: %s", line)
} stderrString += line + "\n"
stderrString += line
default:
line, _ := stdout.ReadString('\n')
if line != "" {
log.Printf("[vagrant driver] stdout: %s", line)
stdoutString += line
}
line, _ = stderr.ReadString('\n')
if line != "" {
log.Printf("[vagrant driver] stderr: %s", line)
stderrString += line
}
time.Sleep(500)
}
} }
}() }()
err = cmd.Wait() for scanOut.Scan() {
line := scanOut.Text()
donech <- true log.Printf("[vagrant driver] stdout: %s", line)
stdoutString += line + "\n"
}
cmd.Wait()
if _, ok := err.(*exec.ExitError); ok { if _, ok := err.(*exec.ExitError); ok {
err = fmt.Errorf("Vagrant error: %s", stderrString) err = fmt.Errorf("Vagrant error: %s", stderrString)

View File

@ -82,7 +82,8 @@ func (s *StepAddBox) Run(ctx context.Context, state multistep.StateBag) multiste
return multistep.ActionContinue return multistep.ActionContinue
} }
ui.Say("Adding box using vagrant box add..") ui.Say("Adding box using vagrant box add ...")
ui.Message("(this can take some time if we need to download the box)")
addArgs := s.generateAddArgs() addArgs := s.generateAddArgs()
log.Printf("[vagrant] Calling box add with following args %s", strings.Join(addArgs, " ")) log.Printf("[vagrant] Calling box add with following args %s", strings.Join(addArgs, " "))