From f1079257ac9930a225b08f2b734b4e0819215e86 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Fri, 8 Dec 2017 10:22:07 -0800 Subject: [PATCH] command: show a special error message when importing in an empty dir If users run "terraform import" in a directory with no Terraform configuration files, it's likely that they've made a mistake either by being in the wrong directory or forgetting to use the -config option on the command line. To help users find their mistake in this case, we'll now produce a specialized error message for this situation: Error: No Terraform configuration files The directory /home/user/example does not contain any Terraform configuration files (.tf or .tf.json). To specify a different configuration directory, use the -config="..." command line option. While here, this also converts some of the other existing messages to diagnostics so that we can show any configuration warnings along with the error message, and move towards the new standard error presentation. --- command/import.go | 51 +++++++++++++++++++----------- command/import_test.go | 32 ++++++++++++++++++- command/test-fixtures/empty/README | 2 ++ 3 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 command/test-fixtures/empty/README diff --git a/command/import.go b/command/import.go index 5123a032f..cbaeec5f4 100644 --- a/command/import.go +++ b/command/import.go @@ -6,12 +6,13 @@ import ( "os" "strings" - "github.com/hashicorp/terraform/tfdiags" + "github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/config/module" "github.com/hashicorp/terraform/terraform" + "github.com/hashicorp/terraform/tfdiags" ) // ImportCommand is a cli.Command implementation that imports resources @@ -78,6 +79,19 @@ func (c *ImportCommand) Run(args []string) int { // Load the module var mod *module.Tree if configPath != "" { + if empty, _ := config.IsEmptyDir(configPath); empty { + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "No Terraform configuration files", + Detail: fmt.Sprintf( + "The directory %s does not contain any Terraform configuration files (.tf or .tf.json). To specify a different configuration directory, use the -config=\"...\" command line option.", + configPath, + ), + }) + c.showDiagnostics(diags) + return 1 + } + var modDiags tfdiags.Diagnostics mod, modDiags = c.Module(configPath) diags = diags.Append(modDiags) @@ -94,11 +108,15 @@ func (c *ImportCommand) Run(args []string) int { targetMod := mod.Child(addr.Path) if targetMod == nil { modulePath := addr.WholeModuleAddress().String() - if modulePath == "" { - c.Ui.Error(importCommandMissingConfigMsg) - } else { - c.Ui.Error(fmt.Sprintf(importCommandMissingModuleFmt, modulePath)) - } + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Import to non-existent module", + Detail: fmt.Sprintf( + "%s is not defined in the configuration. Please add configuration for this module before importing into it.", + modulePath, + ), + }) + c.showDiagnostics(diags) return 1 } rcs := targetMod.Config().Resources @@ -114,6 +132,14 @@ func (c *ImportCommand) Run(args []string) int { if modulePath == "" { modulePath = "the root module" } + + c.showDiagnostics(diags) + + // This is not a diagnostic because currently our diagnostics printer + // doesn't support having a code example in the detail, and there's + // a code example in this message. + // TODO: Improve the diagnostics printer so we can use it for this + // message. c.Ui.Error(fmt.Sprintf( importCommandMissingResourceFmt, addr, modulePath, addr.Type, addr.Name, @@ -296,18 +322,7 @@ const importCommandResourceModeMsg = `Error: resource address must refer to a ma Data resources cannot be imported. ` -const importCommandMissingConfigMsg = `Error: no configuration files in this directory. - -"terraform import" can only be run in a Terraform configuration directory. -Create one or more .tf files in this directory to import here. -` - -const importCommandMissingModuleFmt = `Error: %s does not exist in the configuration. - -Please add the configuration for the module before importing resources into it. -` - -const importCommandMissingResourceFmt = `Error: resource address %q does not exist in the configuration. +const importCommandMissingResourceFmt = `[reset][bold][red]Error:[reset][bold] resource address %q does not exist in the configuration.[reset] Before importing this resource, please create its configuration in %s. For example: diff --git a/command/import_test.go b/command/import_test.go index a75997fab..587c4393f 100644 --- a/command/import_test.go +++ b/command/import_test.go @@ -444,6 +444,36 @@ func TestImport_allowMissingResourceConfig(t *testing.T) { testStateOutput(t, statePath, testImportStr) } +func TestImport_emptyConfig(t *testing.T) { + defer testChdir(t, testFixturePath("empty"))() + + statePath := testTempFile(t) + + p := testProvider() + ui := new(cli.MockUi) + c := &ImportCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(p), + Ui: ui, + }, + } + + args := []string{ + "-state", statePath, + "test_instance.foo", + "bar", + } + code := c.Run(args) + if code != 1 { + t.Fatalf("import succeeded; expected failure") + } + + msg := ui.ErrorWriter.String() + if want := `No Terraform configuration files`; !strings.Contains(msg, want) { + t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg) + } +} + func TestImport_missingResourceConfig(t *testing.T) { defer testChdir(t, testFixturePath("import-missing-resource-config"))() @@ -499,7 +529,7 @@ func TestImport_missingModuleConfig(t *testing.T) { } msg := ui.ErrorWriter.String() - if want := `module.baz does not exist in the configuration`; !strings.Contains(msg, want) { + if want := `module.baz is not defined in the configuration`; !strings.Contains(msg, want) { t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg) } } diff --git a/command/test-fixtures/empty/README b/command/test-fixtures/empty/README new file mode 100644 index 000000000..8f55f302d --- /dev/null +++ b/command/test-fixtures/empty/README @@ -0,0 +1,2 @@ +This directory is intentionally empty, for testing any specialized error +messages that deal with empty configuration directories.