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.
This commit is contained in:
James Bardin 2020-11-30 12:13:54 -05:00
parent 8c1e448b6b
commit 0c3bb316ea
2 changed files with 30 additions and 2 deletions

15
main.go
View File

@ -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 {

View File

@ -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)
}
}