diff --git a/terraform/graph_config_node.go b/terraform/graph_config_node.go index 4ae5144bbe21..abe1e58c1089 100644 --- a/terraform/graph_config_node.go +++ b/terraform/graph_config_node.go @@ -283,6 +283,25 @@ func (n *GraphNodeConfigResource) DependentOn() []string { return result } +// VarWalk calls a callback for all the variables that this resource +// depends on. +func (n *GraphNodeConfigResource) VarWalk(fn func(config.InterpolatedVariable)) { + for _, v := range n.Resource.RawCount.Variables { + fn(v) + } + for _, v := range n.Resource.RawConfig.Variables { + fn(v) + } + for _, p := range n.Resource.Provisioners { + for _, v := range p.ConnInfo.Variables { + fn(v) + } + for _, v := range p.RawConfig.Variables { + fn(v) + } + } +} + func (n *GraphNodeConfigResource) Name() string { result := n.Resource.Id() switch n.DestroyMode { diff --git a/terraform/test-fixtures/transform-resource-count-basic/main.tf b/terraform/test-fixtures/transform-resource-count-basic/main.tf index 83bdd56e66fb..782a9142e4d2 100644 --- a/terraform/test-fixtures/transform-resource-count-basic/main.tf +++ b/terraform/test-fixtures/transform-resource-count-basic/main.tf @@ -1,4 +1,3 @@ resource "aws_instance" "foo" { count = 3 - value = "${aws_instance.foo.0.value}" } diff --git a/terraform/test-fixtures/transform-resource-count-deps/main.tf b/terraform/test-fixtures/transform-resource-count-deps/main.tf new file mode 100644 index 000000000000..c6a683e6ec12 --- /dev/null +++ b/terraform/test-fixtures/transform-resource-count-deps/main.tf @@ -0,0 +1,8 @@ +resource "aws_instance" "foo" { + count = 2 + + provisioner "local-exec" { + command = "echo ${aws_instance.foo.0.id}" + other = "echo ${aws_instance.foo.id}" + } +} diff --git a/terraform/transform_resource.go b/terraform/transform_resource.go index 04c35befc467..498fe20ac604 100644 --- a/terraform/transform_resource.go +++ b/terraform/transform_resource.go @@ -134,8 +134,34 @@ func (n *graphNodeExpandedResource) DependableName() []string { // GraphNodeDependent impl. func (n *graphNodeExpandedResource) DependentOn() []string { - config := &GraphNodeConfigResource{Resource: n.Resource} - return config.DependentOn() + configNode := &GraphNodeConfigResource{Resource: n.Resource} + result := configNode.DependentOn() + + // Walk the variables to find any count-specific variables we depend on. + configNode.VarWalk(func(v config.InterpolatedVariable) { + rv, ok := v.(*config.ResourceVariable) + if !ok { + return + } + + // We only want ourselves + if rv.ResourceId() != n.Resource.Id() { + return + } + + // If this isn't a multi-access (which shouldn't be allowed but + // is verified elsewhere), then we depend on the specific count + // of this resource, ignoring ourself (which again should be + // validated elsewhere). + if rv.Index > -1 { + id := fmt.Sprintf("%s.%d", rv.ResourceId(), rv.Index) + if id != n.stateId() && id != n.stateId()+".0" { + result = append(result, id) + } + } + }) + + return result } // GraphNodeProviderConsumer diff --git a/terraform/transform_resource_test.go b/terraform/transform_resource_test.go index 15c29d43e8ac..6933c622cf96 100644 --- a/terraform/transform_resource_test.go +++ b/terraform/transform_resource_test.go @@ -37,11 +37,33 @@ func TestResourceCountTransformer_countNegative(t *testing.T) { } } +func TestResourceCountTransformer_deps(t *testing.T) { + cfg := testModule(t, "transform-resource-count-deps").Config() + resource := cfg.Resources[0] + + g := Graph{Path: RootModulePath} + { + tf := &ResourceCountTransformer{Resource: resource} + if err := tf.Transform(&g); err != nil { + t.Fatalf("err: %s", err) + } + } + + actual := strings.TrimSpace(g.String()) + expected := strings.TrimSpace(testResourceCountTransformDepsStr) + if actual != expected { + t.Fatalf("bad:\n\n%s", actual) + } +} + const testResourceCountTransformStr = ` aws_instance.foo #0 - aws_instance.foo #2 aws_instance.foo #1 - aws_instance.foo #2 aws_instance.foo #2 - aws_instance.foo #2 +` + +const testResourceCountTransformDepsStr = ` +aws_instance.foo #0 +aws_instance.foo #1 + aws_instance.foo #0 `