completely prune inter-module dependencies
There was a missing outer loop for catching inverse module dependencies when pruning nodes for destroy. Since the need to "register" the fully destroyed modules no longer exists, the extra complication of pruning the modules as a whole from the leaves inward is no longer required. While it is technically still a valid optimization to reduce iterations, the extra comparisons required to backtrack for transitive dependencies don't amount to much, and having a single nested loop is much easier to maintain.
This commit is contained in:
parent
d844d02b87
commit
a6776eaa94
|
@ -2,7 +2,6 @@ package terraform
|
|||
|
||||
import (
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
"github.com/hashicorp/terraform/states"
|
||||
|
@ -188,69 +187,9 @@ func (t *pruneUnusedNodesTransformer) Transform(g *Graph) error {
|
|||
// dependencies from child modules, freeing up nodes in the parent module
|
||||
// to also be removed.
|
||||
|
||||
// First collect the nodes into their respective modules based on
|
||||
// configuration path.
|
||||
moduleMap := make(map[string]pruneUnusedNodesMod)
|
||||
for _, v := range g.Vertices() {
|
||||
var path addrs.Module
|
||||
switch v := v.(type) {
|
||||
case GraphNodeModulePath:
|
||||
path = v.ModulePath()
|
||||
default:
|
||||
continue
|
||||
}
|
||||
m := moduleMap[path.String()]
|
||||
m.addr = path
|
||||
m.nodes = append(m.nodes, v)
|
||||
nodes := g.Vertices()
|
||||
|
||||
moduleMap[path.String()] = m
|
||||
}
|
||||
|
||||
// now we need to restructure the modules so we can sort them
|
||||
var modules []pruneUnusedNodesMod
|
||||
|
||||
for _, mod := range moduleMap {
|
||||
modules = append(modules, mod)
|
||||
}
|
||||
|
||||
// Sort them by path length, longest first, so that we start with the
|
||||
// deepest modules. The order of modules at the same tree level doesn't
|
||||
// matter, we just need to ensure that child modules are processed before
|
||||
// parent modules.
|
||||
sort.Slice(modules, func(i, j int) bool {
|
||||
return len(modules[i].addr) > len(modules[j].addr)
|
||||
})
|
||||
|
||||
for _, mod := range modules {
|
||||
mod.removeUnused(g)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// pruneUnusedNodesMod is a container to hold the nodes that belong to a
|
||||
// particular configuration module for the pruneUnusedNodesTransformer
|
||||
type pruneUnusedNodesMod struct {
|
||||
addr addrs.Module
|
||||
nodes []dag.Vertex
|
||||
}
|
||||
|
||||
// Remove any unused locals, variables, outputs and expanders. Since module
|
||||
// closers can also lookup expansion info to detect orphaned instances, disable
|
||||
// them if their associated expander is removed.
|
||||
func (m *pruneUnusedNodesMod) removeUnused(g *Graph) {
|
||||
// We modify the nodes slice during processing here.
|
||||
// Make a copy so no one is surprised by this changing in the future.
|
||||
nodes := make([]dag.Vertex, len(m.nodes))
|
||||
copy(nodes, m.nodes)
|
||||
|
||||
// since we have no defined structure within the module, just cycle through
|
||||
// the nodes in each module until there are no more removals
|
||||
removed := true
|
||||
for {
|
||||
if !removed {
|
||||
return
|
||||
}
|
||||
for removed := true; removed; {
|
||||
removed = false
|
||||
|
||||
for i := 0; i < len(nodes); i++ {
|
||||
|
@ -307,4 +246,6 @@ func (m *pruneUnusedNodesMod) removeUnused(g *Graph) {
|
|||
}()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue