From 022967acdb273521f037b2a6a412343bc40232a7 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 20 Feb 2015 09:40:41 -0800 Subject: [PATCH] terraform: module inputs/vars can be non-strings [GH-819] --- terraform/context_test.go | 29 +++++++++++++++++++ terraform/eval_variable.go | 12 +++++++- terraform/state.go | 7 ++++- terraform/terraform_test.go | 16 ++++++++++ .../apply-module-bool/child/main.tf | 7 +++++ .../test-fixtures/apply-module-bool/main.tf | 8 +++++ 6 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 terraform/test-fixtures/apply-module-bool/child/main.tf create mode 100644 terraform/test-fixtures/apply-module-bool/main.tf diff --git a/terraform/context_test.go b/terraform/context_test.go index a180154be..0e076cd79 100644 --- a/terraform/context_test.go +++ b/terraform/context_test.go @@ -3298,6 +3298,35 @@ func TestContext2Apply_moduleVarResourceCount(t *testing.T) { } } +// GH-819 +func TestContext2Apply_moduleBool(t *testing.T) { + m := testModule(t, "apply-module-bool") + p := testProvider("aws") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + }) + + if _, err := ctx.Plan(nil); err != nil { + t.Fatalf("err: %s", err) + } + + state, err := ctx.Apply() + if err != nil { + t.Fatalf("err: %s", err) + } + + actual := strings.TrimSpace(state.String()) + expected := strings.TrimSpace(testTerraformApplyModuleBoolStr) + if actual != expected { + t.Fatalf("bad: \n%s", actual) + } +} + func TestContext2Apply_multiProvider(t *testing.T) { m := testModule(t, "apply-multi-provider") p := testProvider("aws") diff --git a/terraform/eval_variable.go b/terraform/eval_variable.go index ebaf2eabb..ced1a0610 100644 --- a/terraform/eval_variable.go +++ b/terraform/eval_variable.go @@ -1,7 +1,11 @@ package terraform import ( + "fmt" + + "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform/config" + "github.com/mitchellh/mapstructure" ) // EvalSetVariables is an EvalNode implementation that sets the variables @@ -34,7 +38,13 @@ func (n *EvalVariableBlock) Eval(ctx EvalContext) (interface{}, error) { // Get our configuration rc := *n.Config for k, v := range rc.Config { - n.Variables[k] = v.(string) + var vStr string + if err := mapstructure.WeakDecode(v, &vStr); err != nil { + return nil, errwrap.Wrapf(fmt.Sprintf( + "%s: error reading value: {{err}}", k), err) + } + + n.Variables[k] = vStr } for k, _ := range rc.Raw { if _, ok := n.Variables[k]; !ok { diff --git a/terraform/state.go b/terraform/state.go index 530d01c08..2ad11a667 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -231,7 +231,12 @@ func (s *State) String() string { s := bufio.NewScanner(strings.NewReader(mStr)) for s.Scan() { - buf.WriteString(fmt.Sprintf(" %s\n", s.Text())) + text := s.Text() + if text != "" { + text = " " + text + } + + buf.WriteString(fmt.Sprintf("%s\n", text)) } } diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index d4b56967f..75f65c36e 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -285,6 +285,22 @@ module.child: type = aws_instance ` +const testTerraformApplyModuleBoolStr = ` +aws_instance.bar: + ID = foo + foo = 1 + type = aws_instance + + Dependencies: + module.child + +module.child: + + Outputs: + + leader = 1 +` + const testTerraformApplyMultiProviderStr = ` aws_instance.bar: ID = foo diff --git a/terraform/test-fixtures/apply-module-bool/child/main.tf b/terraform/test-fixtures/apply-module-bool/child/main.tf new file mode 100644 index 000000000..d2a38434c --- /dev/null +++ b/terraform/test-fixtures/apply-module-bool/child/main.tf @@ -0,0 +1,7 @@ +variable "leader" { + default = false +} + +output "leader" { + value = "${var.leader}" +} diff --git a/terraform/test-fixtures/apply-module-bool/main.tf b/terraform/test-fixtures/apply-module-bool/main.tf new file mode 100644 index 000000000..1d40cd4f4 --- /dev/null +++ b/terraform/test-fixtures/apply-module-bool/main.tf @@ -0,0 +1,8 @@ +module "child" { + source = "./child" + leader = true +} + +resource "aws_instance" "bar" { + foo = "${module.child.leader}" +}