core: Don't create self-references in state

Since StateReferences was implemented on NodeAbstractResource rather than
NodeAbstractResourceInstance it wasn't properly detecting references to
the same instance as self-references.

Now that we are using "seen" to filter out duplicates we can also simplify
how we handle these self-references by just pretending we saw them before
we even start the loop.

This change is confirmed by
TestContext2Apply_provisionerMultiSelfRefSingle
This commit is contained in:
Martin Atkins 2018-09-14 14:11:34 -07:00
parent 9afb0c6c0c
commit 77e50894d5
3 changed files with 22 additions and 20 deletions

View File

@ -270,7 +270,7 @@ func dottedInstanceAddr(tr addrs.ResourceInstance) string {
// StateReferences returns the dependencies to put into the state for
// this resource.
func (n *NodeAbstractResource) StateReferences() []addrs.Referenceable {
func (n *NodeAbstractResourceInstance) StateReferences() []addrs.Referenceable {
selfAddrs := n.ReferenceableAddrs()
// Since we don't include the source location references in our
@ -279,6 +279,18 @@ func (n *NodeAbstractResource) StateReferences() []addrs.Referenceable {
// that additional context.
seen := map[string]struct{}{}
// Pretend that we've already "seen" all of our own addresses so that we
// won't record self-references in the state. This can arise if, for
// example, a provisioner for a resource refers to the resource itself,
// which is valid (since provisioners always run after apply) but should
// not create an explicit dependency edge.
for _, selfAddr := range selfAddrs {
seen[selfAddr.String()] = struct{}{}
if riAddr, ok := selfAddr.(addrs.ResourceInstance); ok {
seen[riAddr.ContainingResource().String()] = struct{}{}
}
}
depsRaw := n.References()
deps := make([]addrs.Referenceable, 0, len(depsRaw))
for _, d := range depsRaw {
@ -300,17 +312,7 @@ func (n *NodeAbstractResource) StateReferences() []addrs.Referenceable {
case addrs.ResourceInstance:
deps = append(deps, tr)
case addrs.Resource:
depStr := tr.String()
selfRef := false
for _, selfAddr := range selfAddrs {
if selfAddr.String() == depStr {
selfRef = true
break
}
}
if !selfRef { // Don't create self-references
deps = append(deps, tr)
}
deps = append(deps, tr)
case addrs.ModuleCallInstance:
deps = append(deps, tr)
default:

View File

@ -726,7 +726,7 @@ aws_instance.foo.1:
type = aws_instance
Dependencies:
aws_instance.foo.0
aws_instance.foo[0]
aws_instance.foo.2:
ID = foo
provider = provider.aws
@ -734,7 +734,7 @@ aws_instance.foo.2:
type = aws_instance
Dependencies:
aws_instance.foo.0
aws_instance.foo[0]
`
const testTerraformApplyProvisionerDiffStr = `

View File

@ -1,9 +1,9 @@
resource "aws_instance" "foo" {
count = 3
foo = "number ${count.index}"
count = 3
foo = "number ${count.index}"
provisioner "shell" {
command = "${aws_instance.foo.0.foo}"
order = "${count.index}"
}
provisioner "shell" {
command = aws_instance.foo[0].foo
order = count.index
}
}