Skip to content

Commit

Permalink
command: validate import resource address early
Browse files Browse the repository at this point in the history
Previously we deferred validation of the resource address on the import
command until we were in the core guts, which caused the error responses
to be rather unhelpful.

By validating these things early we can give better feedback to the user.
  • Loading branch information
apparentlymart committed Jun 9, 2017
1 parent f6305fc commit 7d87191
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 0 deletions.
34 changes: 34 additions & 0 deletions command/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,23 @@ func (c *ImportCommand) Run(args []string) int {
return 1
}

// Validate the provided resource address for syntax
addr, err := terraform.ParseResourceAddress(args[0])
if err != nil {
c.Ui.Error(fmt.Sprintf(importCommandInvalidAddressFmt, err))
return 1
}
if !addr.HasResourceSpec() {
// module.foo target isn't allowed for import
c.Ui.Error(importCommandMissingResourceSpecMsg)
return 1
}
if addr.Mode != config.ManagedResourceMode {
// can't import to a data resource address
c.Ui.Error(importCommandResourceModeMsg)
return 1
}

// Load the module
var mod *module.Tree
if configPath != "" {
Expand Down Expand Up @@ -204,3 +221,20 @@ Options:
func (c *ImportCommand) Synopsis() string {
return "Import existing infrastructure into Terraform"
}

const importCommandInvalidAddressFmt = `Error: %s
For information on valid syntax, see:
https://www.terraform.io/docs/internals/resource-addressing.html
`

const importCommandMissingResourceSpecMsg = `Error: resource address must include a full resource spec
For information on valid syntax, see:
https://www.terraform.io/docs/internals/resource-addressing.html
`

const importCommandResourceModeMsg = `Error: resource address must refer to a managed resource.
Data resources cannot be imported.
`
91 changes: 91 additions & 0 deletions command/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package command

import (
"fmt"
"strings"
"testing"

"github.com/hashicorp/terraform/terraform"
Expand Down Expand Up @@ -315,6 +316,96 @@ func TestImport_customProvider(t *testing.T) {
testStateOutput(t, statePath, testImportCustomProviderStr)
}

func TestImport_dataResource(t *testing.T) {
defer testChdir(t, testFixturePath("import-missing-resource-config"))()

statePath := testTempFile(t)

p := testProvider()
ui := new(cli.MockUi)
c := &ImportCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
},
}

args := []string{
"-state", statePath,
"data.test_data_source.foo",
"bar",
}
code := c.Run(args)
if code != 1 {
t.Fatalf("import succeeded; expected failure")
}

msg := ui.ErrorWriter.String()
if want := `resource address must refer to a managed resource`; !strings.Contains(msg, want) {
t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
}
}

func TestImport_invalidResourceAddr(t *testing.T) {
defer testChdir(t, testFixturePath("import-missing-resource-config"))()

statePath := testTempFile(t)

p := testProvider()
ui := new(cli.MockUi)
c := &ImportCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
},
}

args := []string{
"-state", statePath,
"bananas",
"bar",
}
code := c.Run(args)
if code != 1 {
t.Fatalf("import succeeded; expected failure")
}

msg := ui.ErrorWriter.String()
if want := `invalid resource address "bananas"`; !strings.Contains(msg, want) {
t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
}
}

func TestImport_targetIsModule(t *testing.T) {
defer testChdir(t, testFixturePath("import-missing-resource-config"))()

statePath := testTempFile(t)

p := testProvider()
ui := new(cli.MockUi)
c := &ImportCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
},
}

args := []string{
"-state", statePath,
"module.foo",
"bar",
}
code := c.Run(args)
if code != 1 {
t.Fatalf("import succeeded; expected failure")
}

msg := ui.ErrorWriter.String()
if want := `resource address must include a full resource spec`; !strings.Contains(msg, want) {
t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
}
}

const testImportStr = `
test_instance.foo:
ID = yay
Expand Down
5 changes: 5 additions & 0 deletions command/test-fixtures/import-missing-resource-config/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
provider "test" {

}

# No resource block present, so import fails

0 comments on commit 7d87191

Please sign in to comment.