core: NodeApplyableResource only depends on count and for_each

Only the count and for_each expressions are evaluated by this node type,
so it doesn't need to declare dependencies for any other refs in the
configuration body. Using this more refined set of dependencies means
we can avoid graph cycles in the case where one instance of a resource
refers to another instance of the same resource.

We'll still get cycles if count or for_each self-reference, but that's
forbidden anyway (caught during validate) and makes sense because those
two are whole-resource-level config rather than per-instance config.
This commit is contained in:
Martin Atkins 2018-09-12 16:56:06 -07:00
parent d2c134a80e
commit 64eb5f732c
1 changed files with 24 additions and 0 deletions

View File

@ -2,6 +2,10 @@ package terraform
import ( import (
"log" "log"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/dag"
"github.com/hashicorp/terraform/lang"
) )
// NodeApplyableResource represents a resource that is "applyable": // NodeApplyableResource represents a resource that is "applyable":
@ -21,12 +25,32 @@ var (
_ GraphNodeEvalable = (*NodeApplyableResource)(nil) _ GraphNodeEvalable = (*NodeApplyableResource)(nil)
_ GraphNodeProviderConsumer = (*NodeApplyableResource)(nil) _ GraphNodeProviderConsumer = (*NodeApplyableResource)(nil)
_ GraphNodeAttachResourceConfig = (*NodeApplyableResource)(nil) _ GraphNodeAttachResourceConfig = (*NodeApplyableResource)(nil)
_ GraphNodeReferencer = (*NodeApplyableResource)(nil)
) )
func (n *NodeApplyableResource) Name() string { func (n *NodeApplyableResource) Name() string {
return n.NodeAbstractResource.Name() + " (prepare state)" return n.NodeAbstractResource.Name() + " (prepare state)"
} }
func (n *NodeApplyableResource) References() []*addrs.Reference {
if n.Config == nil {
log.Printf("[WARN] NodeApplyableResource %q: no configuration, so can't determine References", dag.VertexName(n))
return nil
}
var result []*addrs.Reference
// Since this node type only updates resource-level metadata, we only
// need to worry about the parts of the configuration that affect
// our "each mode": the count and for_each meta-arguments.
refs, _ := lang.ReferencesInExpr(n.Config.Count)
result = append(result, refs...)
refs, _ = lang.ReferencesInExpr(n.Config.ForEach)
result = append(result, refs...)
return result
}
// GraphNodeEvalable // GraphNodeEvalable
func (n *NodeApplyableResource) EvalTree() EvalNode { func (n *NodeApplyableResource) EvalTree() EvalNode {
addr := n.ResourceAddr() addr := n.ResourceAddr()