From f50c7acf9521ed11dc8226be5abd97dff788864d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 23 Nov 2016 09:25:20 -0800 Subject: [PATCH] terraform: record dependency to self (other index) Fixes #10313 The new graph wasn't properly recording resource dependencies to a specific index of itself. For example: `foo.bar.2` depending on `foo.bar.0` wasn't shown in the state when it should've been. This adds a test to verify this and fixes it. --- terraform/context_apply_test.go | 60 +++++++++++++++++++ terraform/node_resource_apply.go | 5 +- terraform/terraform_test.go | 21 +++++++ .../main.tf | 9 +++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 terraform/test-fixtures/apply-provisioner-multi-self-ref-single/main.tf diff --git a/terraform/context_apply_test.go b/terraform/context_apply_test.go index 5b17533f1..6dd499edb 100644 --- a/terraform/context_apply_test.go +++ b/terraform/context_apply_test.go @@ -3611,6 +3611,66 @@ func TestContext2Apply_provisionerMultiSelfRef(t *testing.T) { } } +func TestContext2Apply_provisionerMultiSelfRefSingle(t *testing.T) { + var lock sync.Mutex + order := make([]string, 0, 5) + + m := testModule(t, "apply-provisioner-multi-self-ref-single") + p := testProvider("aws") + pr := testProvisioner() + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { + lock.Lock() + defer lock.Unlock() + + val, ok := c.Config["order"] + if !ok { + t.Fatalf("bad value for order: %v %#v", val, c) + } + + order = append(order, val.(string)) + return nil + } + + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + Provisioners: map[string]ResourceProvisionerFactory{ + "shell": testProvisionerFuncFixed(pr), + }, + }) + + if _, err := ctx.Plan(); 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(testTerraformApplyProvisionerMultiSelfRefSingleStr) + if actual != expected { + t.Fatalf("bad: \n%s", actual) + } + + // Verify apply was invoked + if !pr.ApplyCalled { + t.Fatalf("provisioner not invoked") + } + + // Verify our result + sort.Strings(order) + expectedOrder := []string{"0", "1", "2"} + if !reflect.DeepEqual(order, expectedOrder) { + t.Fatalf("bad: %#v", order) + } +} + func TestContext2Apply_provisionerMultiSelfRefCount(t *testing.T) { var lock sync.Mutex commands := make([]string, 0, 5) diff --git a/terraform/node_resource_apply.go b/terraform/node_resource_apply.go index f609b7dd5..87bc205d0 100644 --- a/terraform/node_resource_apply.go +++ b/terraform/node_resource_apply.go @@ -47,7 +47,10 @@ func (n *NodeApplyableResource) EvalTree() EvalNode { // code for this that we've used for a long time. var stateDeps []string { - oldN := &graphNodeExpandedResource{Resource: n.Config} + oldN := &graphNodeExpandedResource{ + Resource: n.Config, + Index: addr.Index, + } stateDeps = oldN.StateDependencies() } diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index 453e8b79f..40e4935ac 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -603,6 +603,27 @@ aws_instance.foo.2: type = aws_instance ` +const testTerraformApplyProvisionerMultiSelfRefSingleStr = ` +aws_instance.foo.0: + ID = foo + foo = number 0 + type = aws_instance +aws_instance.foo.1: + ID = foo + foo = number 1 + type = aws_instance + + Dependencies: + aws_instance.foo.0 +aws_instance.foo.2: + ID = foo + foo = number 2 + type = aws_instance + + Dependencies: + aws_instance.foo.0 +` + const testTerraformApplyProvisionerDiffStr = ` aws_instance.bar: ID = foo diff --git a/terraform/test-fixtures/apply-provisioner-multi-self-ref-single/main.tf b/terraform/test-fixtures/apply-provisioner-multi-self-ref-single/main.tf new file mode 100644 index 000000000..d033651b1 --- /dev/null +++ b/terraform/test-fixtures/apply-provisioner-multi-self-ref-single/main.tf @@ -0,0 +1,9 @@ +resource "aws_instance" "foo" { + count = 3 + foo = "number ${count.index}" + + provisioner "shell" { + command = "${aws_instance.foo.0.foo}" + order = "${count.index}" + } +}