prune unused resources from apply

If a resource is only destroying instances, there is no reason to
prepare the state and we can remove the Resource (prepare state) nodes.
They normally have pose no issue, but if the instances are being
destroyed along with their dependencies, the resource node may fail to
evaluate due to the missing dependencies (since destroy happens in the
reverse order).

These failures were previously blocked by there being a cycle when the
destroy nodes were directly attached to the resource nodes.
This commit is contained in:
James Bardin 2019-09-28 20:34:55 -04:00
parent 7108560228
commit f766bb8380
1 changed files with 42 additions and 0 deletions

View File

@ -277,5 +277,47 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error {
} }
} }
return t.pruneResources(g)
}
// If there are only destroy instances for a particular resource, there's no
// reason for the resource node to prepare the state. Remove Resource nodes so
// that they don't fail by trying to evaluate a resource that is only being
// destroyed along with its dependencies.
func (t *DestroyEdgeTransformer) pruneResources(g *Graph) error {
for _, v := range g.Vertices() {
n, ok := v.(*NodeApplyableResource)
if !ok {
continue
}
// if there are only destroy dependencies, we don't need this node
des, err := g.Descendents(n)
if err != nil {
return err
}
descendents := des.List()
nonDestroyInstanceFound := false
for _, v := range descendents {
if _, ok := v.(*NodeApplyableResourceInstance); ok {
nonDestroyInstanceFound = true
break
}
}
if nonDestroyInstanceFound {
continue
}
// connect all the through-edges, then delete the node
for _, d := range g.DownEdges(n).List() {
for _, u := range g.UpEdges(n).List() {
g.Connect(dag.BasicEdge(u, d))
}
}
log.Printf("DestroyEdgeTransformer: pruning unused resource node %s", dag.VertexName(n))
g.Remove(n)
}
return nil return nil
} }