From 820ed4881329333f3b9519fac64cef39cc487514 Mon Sep 17 00:00:00 2001 From: Alisdair McDiarmid Date: Thu, 18 Jun 2020 17:56:05 -0400 Subject: [PATCH] command: Fix init flags silent exit bug When using `-flag=value` with Powershell, unquoted values are broken into separate arguments. This means that the following command: terraform init -backend-config=./backend.conf is interpreted by Terraform as: terraform init -backend-config= ./backend.conf This results in an empty backend-config setting (which is semantically valid!) followed by a custom configuration path (pointing at a file). Due to a bug where we could exit without printing diagnostics, this would result in a silent failure that was very difficult to diagnose. --- command/init.go | 1 + command/init_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/command/init.go b/command/init.go index 4297f6ab2..547e6f4e5 100644 --- a/command/init.go +++ b/command/init.go @@ -137,6 +137,7 @@ func (c *InitCommand) Run(args []string) int { empty, err := configs.IsEmptyDir(path) if err != nil { diags = diags.Append(fmt.Errorf("Error checking configuration: %s", err)) + c.showDiagnostics(diags) return 1 } if empty { diff --git a/command/init_test.go b/command/init_test.go index 7ba7a6815..4028fd7d2 100644 --- a/command/init_test.go +++ b/command/init_test.go @@ -357,6 +357,40 @@ func TestInit_backendConfigFile(t *testing.T) { } } +func TestInit_backendConfigFilePowershellConfusion(t *testing.T) { + // Create a temporary working directory that is empty + td := tempDir(t) + copy.CopyDir(testFixturePath("init-backend-config-file"), td) + defer os.RemoveAll(td) + defer testChdir(t, td)() + + ui := new(cli.MockUi) + c := &InitCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + }, + } + + // SUBTLE: when using -flag=value with Powershell, unquoted values are + // broken into separate arguments. This results in the init command + // interpreting the flags as an empty backend-config setting (which is + // semantically valid!) followed by a custom configuration path. + // + // Adding the "=" here forces this codepath to be checked, and it should + // result in an early exit with a diagnostic that the provided + // configuration file is not a diretory. + args := []string{"-backend-config=", "./input.config"} + if code := c.Run(args); code != 1 { + t.Fatalf("got exit status %d; want 1\nstderr:\n%s\n\nstdout:\n%s", code, ui.ErrorWriter.String(), ui.OutputWriter.String()) + } + + output := ui.ErrorWriter.String() + if got, want := output, `Module directory ./input.config does not exist`; !strings.Contains(got, want) { + t.Fatalf("wrong output\ngot:\n%s\n\nwant: message containing %q", got, want) + } +} + func TestInit_backendConfigFileChange(t *testing.T) { // Create a temporary working directory that is empty td := tempDir(t)