diff --git a/packer/environment.go b/packer/environment.go index a7067a682..245672d05 100644 --- a/packer/environment.go +++ b/packer/environment.go @@ -83,6 +83,7 @@ func DefaultEnvironmentConfig() *EnvironmentConfig { config.Ui = &BasicUi{ Reader: os.Stdin, Writer: os.Stdout, + ErrorWriter: os.Stderr, } return config diff --git a/packer/environment_test.go b/packer/environment_test.go index 65bc83057..7a16803e4 100644 --- a/packer/environment_test.go +++ b/packer/environment_test.go @@ -32,6 +32,7 @@ func testEnvironment() Environment { config.Ui = &BasicUi{ Reader: new(bytes.Buffer), Writer: new(bytes.Buffer), + ErrorWriter: new(bytes.Buffer), } env, err := NewEnvironment(config) diff --git a/packer/ui.go b/packer/ui.go index e3f25be89..4b082b38e 100644 --- a/packer/ui.go +++ b/packer/ui.go @@ -61,6 +61,7 @@ type TargettedUi struct { type BasicUi struct { Reader io.Reader Writer io.Writer + ErrorWriter io.Writer l sync.Mutex interrupted bool } @@ -235,8 +236,13 @@ func (rw *BasicUi) Error(message string) { rw.l.Lock() defer rw.l.Unlock() + writer := rw.ErrorWriter + if writer == nil { + writer = rw.Writer + } + log.Printf("ui error: %s", message) - _, err := fmt.Fprint(rw.Writer, message+"\n") + _, err := fmt.Fprint(writer, message+"\n") if err != nil { log.Printf("[ERR] Failed to write to UI: %s", err) } diff --git a/packer/ui_test.go b/packer/ui_test.go index d512d8d13..3dd8208e5 100644 --- a/packer/ui_test.go +++ b/packer/ui_test.go @@ -7,10 +7,27 @@ import ( "testing" ) +// This reads the output from the bytes.Buffer in our test object +// and then resets the buffer. +func readWriter(ui *BasicUi) (result string) { + buffer := ui.Writer.(*bytes.Buffer) + result = buffer.String() + buffer.Reset() + return +} + +func readErrorWriter(ui *BasicUi) (result string) { + buffer := ui.ErrorWriter.(*bytes.Buffer) + result = buffer.String() + buffer.Reset() + return +} + func testUi() *BasicUi { return &BasicUi{ Reader: new(bytes.Buffer), Writer: new(bytes.Buffer), + ErrorWriter: new(bytes.Buffer), } } @@ -32,6 +49,11 @@ func TestColoredUi(t *testing.T) { ui.Error("foo") result = readWriter(bufferUi) + if result != "" { + t.Fatalf("invalid output: %s", result) + } + + result = readErrorWriter(bufferUi) if result != "\033[1;31mfoo\033[0m\n" { t.Fatalf("invalid output: %s", result) } @@ -59,7 +81,7 @@ func TestColoredUi_noColorEnv(t *testing.T) { } ui.Error("foo") - result = readWriter(bufferUi) + result = readErrorWriter(bufferUi) if result != "foo\n" { t.Fatalf("invalid output: %s", result) } @@ -88,7 +110,7 @@ func TestTargettedUi(t *testing.T) { } targettedUi.Error("bar") - actual = readWriter(bufferUi) + actual = readErrorWriter(bufferUi) expected = "==> foo: bar\n" if actual != expected { t.Fatalf("bad: %#v", actual) @@ -131,12 +153,13 @@ func TestBasicUi_Error(t *testing.T) { var actual, expected string bufferUi.Error("foo") - actual = readWriter(bufferUi) + actual = readErrorWriter(bufferUi) expected = "foo\n" if actual != expected { t.Fatalf("bad: %#v", actual) } + bufferUi.ErrorWriter = nil bufferUi.Error("5") actual = readWriter(bufferUi) expected = "5\n" @@ -214,12 +237,3 @@ func TestMachineReadableUi(t *testing.T) { t.Fatalf("bad: %#v", data) } } - -// This reads the output from the bytes.Buffer in our test object -// and then resets the buffer. -func readWriter(ui *BasicUi) (result string) { - buffer := ui.Writer.(*bytes.Buffer) - result = buffer.String() - buffer.Reset() - return -}