add DestroyValueReferenceTransformer

DestroyValueReferenceTransformer is used during destroy to reverse the
edges for output and local values. Because destruction is going to
remove these from the state, nodes that depend on their value need to be
visited first.
This commit is contained in:
James Bardin 2017-09-29 11:12:57 -04:00
parent 3414e1b996
commit 35c6a4e89d
3 changed files with 41 additions and 0 deletions

View File

@ -120,6 +120,13 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
// Connect references so ordering is correct
&ReferenceTransformer{},
// Reverse the edges to outputs and locals, so that
// interpolations don't fail during destroy.
GraphTransformIf(
func() bool { return b.Destroy },
&DestroyValueReferenceTransformer{},
),
// Add the node to fix the state count boundaries
&CountBoundaryTransformer{},

View File

@ -119,6 +119,9 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error {
return &NodeApplyableProvider{NodeAbstractProvider: a}
}
steps := []GraphTransformer{
// Add the local values
&LocalTransformer{Module: t.Module},
// Add outputs and metadata
&OutputTransformer{Module: t.Module},
&AttachResourceConfigTransformer{Module: t.Module},

View File

@ -76,6 +76,37 @@ func (t *ReferenceTransformer) Transform(g *Graph) error {
return nil
}
// DestroyReferenceTransformer is a GraphTransformer that reverses the edges
// for nodes that depend on an Output or Local value. Output and local nodes are
// removed during destroy, so anything which depends on them must be evaluated
// first. These can't be interpolated during destroy, so the stored value must
// be used anyway hence they don't need to be re-evaluated.
type DestroyValueReferenceTransformer struct{}
func (t *DestroyValueReferenceTransformer) Transform(g *Graph) error {
vs := g.Vertices()
for _, v := range vs {
switch v.(type) {
case *NodeApplyableOutput, *NodeLocal:
// OK
default:
continue
}
// reverse any incoming edges so that the value is removed last
for _, e := range g.EdgesTo(v) {
source := e.Source()
log.Printf("[TRACE] output dep: %s", dag.VertexName(source))
g.RemoveEdge(e)
g.Connect(&DestroyEdge{S: v, T: source})
}
}
return nil
}
// ReferenceMap is a structure that can be used to efficiently check
// for references on a graph.
type ReferenceMap struct {