blob: b22ef11fc0f739a110dff460185bc247987091f4 [file] [log] [blame]
package terraform
import (
"github.com/hashicorp/terraform/internal/dag"
)
const rootNodeName = "root"
// RootTransformer is a GraphTransformer that adds a root to the graph.
type RootTransformer struct{}
func (t *RootTransformer) Transform(g *Graph) error {
// If we already have a good root, we're done
if _, err := g.Root(); err == nil {
return nil
}
// We intentionally add a graphNodeRoot value -- rather than a pointer to
// one -- so that all root nodes will coalesce together if two graphs
// are merged. Each distinct node value can only be in a graph once,
// so adding another graphNodeRoot value to the same graph later will
// be a no-op and all of the edges from root nodes will coalesce together
// under Graph.Subsume.
//
// It's important to retain this coalescing guarantee under future
// maintenence.
var root graphNodeRoot
g.Add(root)
// We initially make the root node depend on every node except itself.
// If the caller subsequently runs transitive reduction on the graph then
// it's typical for some of these edges to then be removed.
for _, v := range g.Vertices() {
if v == root {
continue
}
if g.UpEdges(v).Len() == 0 {
g.Connect(dag.BasicEdge(root, v))
}
}
return nil
}
type graphNodeRoot struct{}
func (n graphNodeRoot) Name() string {
return rootNodeName
}
// CloseRootModuleTransformer is a GraphTransformer that adds a root to the graph.
type CloseRootModuleTransformer struct{}
func (t *CloseRootModuleTransformer) Transform(g *Graph) error {
// close the root module
closeRoot := &nodeCloseModule{}
g.Add(closeRoot)
// since this is closing the root module, make it depend on everything in
// the root module.
for _, v := range g.Vertices() {
if v == closeRoot {
continue
}
// since this is closing the root module, and must be last, we can
// connect to anything that doesn't have any up edges.
if g.UpEdges(v).Len() == 0 {
g.Connect(dag.BasicEdge(closeRoot, v))
}
}
return nil
}