From 0c3bb316ea56aacf5108883d1a269a53744fdd43 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Mon, 30 Nov 2020 12:13:54 -0500 Subject: [PATCH] redirect warnigns to stdout The default cli Warn calls always write to the error writer (stderr by default), however the output is intended to be viewed in the UI by the user, rather than in a separate stream. Terraform also generally does not consider warnings to be errors from the cli point of view, and does not need to output the warning text to stderr. By redirecting Warn calls to Output calls at the lowest level in the main package, we can eliminate the chance that Warn and Output messages are interleaved, while still allowing the internal `cli.Ui` implementations to format `Warn` and `Output` calls separately. --- main.go | 15 +++++++++++++-- main_test.go | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 2d26bb508..0b7f9c1d4 100644 --- a/main.go +++ b/main.go @@ -36,6 +36,17 @@ const ( envTmpLogPath = "TF_TEMP_LOG_PATH" ) +// ui wraps the primary output cli.Ui, and redirects Warn calls to Output +// calls. This ensures that warnings are sent to stdout, and are properly +// serialized within the stdout stream. +type ui struct { + cli.Ui +} + +func (u *ui) Warn(msg string) { + u.Ui.Output(msg) +} + func main() { os.Exit(realMain()) } @@ -82,11 +93,11 @@ func realMain() int { } func init() { - Ui = &cli.BasicUi{ + Ui = &ui{&cli.BasicUi{ Writer: os.Stdout, ErrorWriter: os.Stderr, Reader: os.Stdin, - } + }} } func wrappedMain() int { diff --git a/main_test.go b/main_test.go index 406195e8b..9b9594f10 100644 --- a/main_test.go +++ b/main_test.go @@ -264,3 +264,20 @@ func (c *testCommandCLI) Run(args []string) int { func (c *testCommandCLI) Synopsis() string { return "" } func (c *testCommandCLI) Help() string { return "" } + +func TestWarnOutput(t *testing.T) { + mock := cli.NewMockUi() + wrapped := &ui{mock} + wrapped.Warn("WARNING") + + stderr := mock.ErrorWriter.String() + stdout := mock.OutputWriter.String() + + if stderr != "" { + t.Fatalf("unexpected stderr: %q", stderr) + } + + if stdout != "WARNING\n" { + t.Fatalf("unexpected stdout: %q\n", stdout) + } +}