Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions command/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,76 @@ func TestImportModuleVarFile(t *testing.T) {
}
}

// This test covers an edge case where a module with a complex input variable
// of nested objects has an invalid default which is overridden by the calling
// context, and is used in locals. If we don't evaluate module call variables
// for the import walk, this results in an error.
//
// The specific example has a variable "foo" which is a nested object:
//
// foo = { bar = { baz = true } }
//
// This is used as foo = var.foo in the call to the child module, which then
// uses the traversal foo.bar.baz in a local. A default value in the child
// module of {} causes this local evaluation to error, breaking import.
func TestImportModuleInputVariableEvaluation(t *testing.T) {
td := tempDir(t)
copy.CopyDir(testFixturePath("import-module-input-variable"), td)
defer os.RemoveAll(td)
defer testChdir(t, td)()

statePath := testTempFile(t)

p := testProvider()
p.GetSchemaReturn = &terraform.ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"test_instance": {
Attributes: map[string]*configschema.Attribute{
"foo": {Type: cty.String, Optional: true},
},
},
},
}

providerSource, close := newMockProviderSource(t, map[string][]string{
"test": {"1.2.3"},
})
defer close()

// init to install the module
ui := new(cli.MockUi)
m := Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
ProviderSource: providerSource,
}

ic := &InitCommand{
Meta: m,
}
if code := ic.Run([]string{}); code != 0 {
t.Fatalf("init failed\n%s", ui.ErrorWriter)
}

// import
ui = new(cli.MockUi)
c := &ImportCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
},
}
args := []string{
"-state", statePath,
"module.child.test_instance.foo",
"bar",
}
code := c.Run(args)
if code != 0 {
t.Fatalf("import failed; expected success")
}
}

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

Expand Down
11 changes: 11 additions & 0 deletions command/testdata/import-module-input-variable/child/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
variable "foo" {
default = {}
}

locals {
baz = var.foo.bar.baz
}

resource "test_instance" "foo" {
foo = local.baz
}
8 changes: 8 additions & 0 deletions command/testdata/import-module-input-variable/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
variable "foo" {
default = {}
}

module "child" {
source = "./child"
foo = var.foo
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo = { bar = { baz = true } }
2 changes: 1 addition & 1 deletion terraform/node_module_variable.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func (n *nodeModuleVariable) EvalTree() EvalNode {
Nodes: []EvalNode{
&EvalOpFilter{
Ops: []walkOperation{walkRefresh, walkPlan, walkApply,
walkDestroy},
walkDestroy, walkImport},
Node: &EvalModuleCallArgument{
Addr: n.Addr.Variable,
Config: n.Config,
Expand Down