core: Local and output values must reference destroy nodes too
Because we currently rely on the ReferenceTransformer to introduce the necessary edges between local/output values and resource destroy nodes, we must include the destroy phase of any resource we depend on in the references of these. This works in conjunction with the changes in the prior commit to restore correct handling of dependencies for local and output values during destroy. With the current design, several seemingly-separate parts of the code must all coincidentally agree with one another for destroy edges to be created properly, which makes this code very hard to maintain. In future we should refactor this so that ReferenceTransformer doesn't create edges for destroy nodes at all, and have _all_ destroy edges (including create_before_destroy) be dealt with in the single DestroyEdgeTransformer, where they can be maintained and unit tested together.
This commit is contained in:
parent
6bbfbab93e
commit
de7b834de7
|
@ -47,7 +47,7 @@ func (n *NodeLocal) ReferenceableAddrs() []addrs.Referenceable {
|
|||
// GraphNodeReferencer
|
||||
func (n *NodeLocal) References() []*addrs.Reference {
|
||||
refs, _ := lang.ReferencesInExpr(n.Config.Expr)
|
||||
return refs
|
||||
return appendResourceDestroyReferences(refs)
|
||||
}
|
||||
|
||||
// GraphNodeEvalable
|
||||
|
|
|
@ -108,7 +108,7 @@ func referencesForOutput(c *configs.Output) []*addrs.Reference {
|
|||
|
||||
// GraphNodeReferencer
|
||||
func (n *NodeApplyableOutput) References() []*addrs.Reference {
|
||||
return referencesForOutput(n.Config)
|
||||
return appendResourceDestroyReferences(referencesForOutput(n.Config))
|
||||
}
|
||||
|
||||
// GraphNodeEvalable
|
||||
|
|
|
@ -453,6 +453,29 @@ func ReferenceFromInterpolatedVar(v config.InterpolatedVariable) []string {
|
|||
}
|
||||
}
|
||||
|
||||
// appendResourceDestroyReferences identifies resource and resource instance
|
||||
// references in the given slice and appends to it the "destroy-phase"
|
||||
// equivalents of those references, returning the result.
|
||||
//
|
||||
// This can be used in the References implementation for a node which must also
|
||||
// depend on the destruction of anything it references.
|
||||
func appendResourceDestroyReferences(refs []*addrs.Reference) []*addrs.Reference {
|
||||
given := refs
|
||||
for _, ref := range given {
|
||||
switch tr := ref.Subject.(type) {
|
||||
case addrs.Resource:
|
||||
newRef := *ref // shallow copy
|
||||
newRef.Subject = tr.Phase(addrs.ResourceInstancePhaseDestroy)
|
||||
refs = append(refs, &newRef)
|
||||
case addrs.ResourceInstance:
|
||||
newRef := *ref // shallow copy
|
||||
newRef.Subject = tr.Phase(addrs.ResourceInstancePhaseDestroy)
|
||||
refs = append(refs, &newRef)
|
||||
}
|
||||
}
|
||||
return refs
|
||||
}
|
||||
|
||||
func modulePrefixStr(p addrs.ModuleInstance) string {
|
||||
return p.String()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue