diff --git a/command/013_config_upgrade.go b/command/013_config_upgrade.go index 997f44f77..890752384 100644 --- a/command/013_config_upgrade.go +++ b/command/013_config_upgrade.go @@ -30,7 +30,11 @@ const skippedConfigurationFileWarning = "The %s configuration file %q was skippe func (c *ZeroThirteenUpgradeCommand) Run(args []string) int { args = c.Meta.process(args) + + var skipConfirm bool + flags := c.Meta.defaultFlagSet("0.13upgrade") + flags.BoolVar(&skipConfirm, "yes", false, "skip confirmation prompt") flags.Usage = func() { c.Ui.Error(c.Help()) } if err := flags.Parse(args); err != nil { return 1 @@ -104,7 +108,7 @@ func (c *ZeroThirteenUpgradeCommand) Run(args []string) int { if strings.HasSuffix(strings.ToLower(path), ".json") { diags = diags.Append(tfdiags.Sourceless( tfdiags.Warning, - "JSON configuration file was not rewritten", + "JSON configuration file ignored", fmt.Sprintf( skippedConfigurationFileWarning, "JSON", @@ -126,12 +130,44 @@ func (c *ZeroThirteenUpgradeCommand) Run(args []string) int { return 1 } + // Explain what the command does and how to use it, and ask for confirmation. + if !skipConfirm { + c.Ui.Output(fmt.Sprintf(` +This command will update the configuration files in the given directory to use +the new provider source features from Terraform v0.13. It will also highlight +any providers for which the source cannot be detected, and advise how to +proceed. + +We recommend using this command in a clean version control work tree, so that +you can easily see the proposed changes as a diff against the latest commit. +If you have uncommited changes already present, we recommend aborting this +command and dealing with them before running this command again. +`)) + + query := "Would you like to upgrade the module in the current directory?" + if dir != "." { + query = fmt.Sprintf("Would you like to upgrade the module in %s?", dir) + } + v, err := c.Ui.Ask(query) + if err != nil { + diags = diags.Append(err) + c.showDiagnostics(diags) + return 1 + } + if v != "yes" { + c.Ui.Info("Upgrade cancelled.") + return 0 + } + + c.Ui.Output(`-----------------------------------------------------------------------------`) + } + // It's not clear what the correct behaviour is for upgrading override // files. For now, just log that we're ignoring the file. for _, path := range overrides { diags = diags.Append(tfdiags.Sourceless( tfdiags.Warning, - "Override configuration file was not rewritten", + "Override configuration file ignored", fmt.Sprintf( skippedConfigurationFileWarning, "override", diff --git a/command/013_config_upgrade_test.go b/command/013_config_upgrade_test.go index d0a7fa23f..195c30a78 100644 --- a/command/013_config_upgrade_test.go +++ b/command/013_config_upgrade_test.go @@ -1,6 +1,7 @@ package command import ( + "bytes" "fmt" "io/ioutil" "net/http" @@ -123,7 +124,7 @@ func TestZeroThirteenUpgrade_success(t *testing.T) { }, } - if code := c.Run(nil); code != 0 { + if code := c.Run([]string{"-yes"}); code != 0 { t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) } @@ -173,7 +174,7 @@ func TestZeroThirteenUpgrade_submodule(t *testing.T) { } // Here we pass a target module directory to process - if code := c.Run([]string{"module"}); code != 0 { + if code := c.Run([]string{"-yes", "module"}); code != 0 { t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) } @@ -203,7 +204,7 @@ func TestZeroThirteenUpgrade_skippedFiles(t *testing.T) { }, } - if code := c.Run(nil); code != 0 { + if code := c.Run([]string{"-yes"}); code != 0 { t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) } @@ -221,6 +222,67 @@ func TestZeroThirteenUpgrade_skippedFiles(t *testing.T) { } } +func TestZeroThirteenUpgrade_confirm(t *testing.T) { + inputPath := testFixturePath(path.Join("013upgrade-explicit-providers", "input")) + + td := tempDir(t) + copy.CopyDir(inputPath, td) + defer os.RemoveAll(td) + defer testChdir(t, td)() + + ui := new(cli.MockUi) + inputBuf := &bytes.Buffer{} + ui.InputReader = inputBuf + inputBuf.WriteString("yes") + c := &ZeroThirteenUpgradeCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + }, + } + + if code := c.Run(nil); code != 0 { + t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) + } + + output := ui.OutputWriter.String() + if !strings.Contains(output, "Upgrade complete") { + t.Fatal("unexpected output:", output) + } +} + +func TestZeroThirteenUpgrade_cancel(t *testing.T) { + inputPath := testFixturePath(path.Join("013upgrade-explicit-providers", "input")) + + td := tempDir(t) + copy.CopyDir(inputPath, td) + defer os.RemoveAll(td) + defer testChdir(t, td)() + + ui := new(cli.MockUi) + inputBuf := &bytes.Buffer{} + ui.InputReader = inputBuf + inputBuf.WriteString("no") + c := &ZeroThirteenUpgradeCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + }, + } + + if code := c.Run(nil); code != 0 { + t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) + } + + output := ui.OutputWriter.String() + if !strings.Contains(output, "Upgrade cancelled") { + t.Fatal("unexpected output:", output) + } + if strings.Contains(output, "Upgrade complete") { + t.Fatal("unexpected output:", output) + } +} + func TestZeroThirteenUpgrade_unsupportedVersion(t *testing.T) { inputPath := testFixturePath("013upgrade-unsupported-version") @@ -237,7 +299,7 @@ func TestZeroThirteenUpgrade_unsupportedVersion(t *testing.T) { }, } - if code := c.Run(nil); code == 0 { + if code := c.Run([]string{"-yes"}); code == 0 { t.Fatal("expected error, got:", ui.OutputWriter) } @@ -309,7 +371,7 @@ func TestZeroThirteenUpgrade_empty(t *testing.T) { }, } - if code := c.Run(nil); code == 0 { + if code := c.Run([]string{"-yes"}); code == 0 { t.Fatal("expected error, got:", ui.OutputWriter) }