mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 01:41:48 -06:00
138 lines
3.4 KiB
Go
138 lines
3.4 KiB
Go
package terraform
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/terraform/config/module"
|
|
"github.com/hashicorp/terraform/dag"
|
|
)
|
|
|
|
// OrphanTransformer is a GraphTransformer that adds orphans to the
|
|
// graph. This transformer adds both resource and module orphans.
|
|
type OrphanTransformer struct {
|
|
// State is the global state. We require the global state to
|
|
// properly find module orphans at our path.
|
|
State *State
|
|
|
|
// Module is the root module. We'll look up the proper configuration
|
|
// using the graph path.
|
|
Module *module.Tree
|
|
}
|
|
|
|
func (t *OrphanTransformer) Transform(g *Graph) error {
|
|
state := t.State.ModuleByPath(g.Path)
|
|
if state == nil {
|
|
// If there is no state for our module, there can't be any orphans
|
|
return nil
|
|
}
|
|
|
|
module := t.Module.Child(g.Path[1:])
|
|
if module == nil {
|
|
panic(fmt.Sprintf(
|
|
"module not found for path: %#v",
|
|
g.Path[1:]))
|
|
}
|
|
config := module.Config()
|
|
|
|
// Go over each resource orphan and add it to the graph.
|
|
resourceOrphans := state.Orphans(config)
|
|
resourceVertexes := make([]dag.Vertex, len(resourceOrphans))
|
|
for i, k := range resourceOrphans {
|
|
resourceVertexes[i] = g.Add(&graphNodeOrphanResource{
|
|
ResourceName: k,
|
|
dependentOn: state.Resources[k].Dependencies,
|
|
})
|
|
}
|
|
|
|
// Go over each module orphan and add it to the graph. We store the
|
|
// vertexes and states outside so that we can connect dependencies later.
|
|
moduleOrphans := t.State.ModuleOrphans(g.Path, config)
|
|
moduleVertexes := make([]dag.Vertex, len(moduleOrphans))
|
|
for i, path := range moduleOrphans {
|
|
moduleVertexes[i] = g.Add(&graphNodeOrphanModule{
|
|
Path: path,
|
|
dependentOn: t.State.ModuleByPath(path).Dependencies,
|
|
})
|
|
}
|
|
|
|
// Now do the dependencies. We do this _after_ adding all the orphan
|
|
// nodes above because there are cases in which the orphans themselves
|
|
// depend on other orphans.
|
|
|
|
// Resource dependencies
|
|
for _, v := range resourceVertexes {
|
|
g.ConnectDependent(v)
|
|
}
|
|
|
|
// Module dependencies
|
|
for _, v := range moduleVertexes {
|
|
g.ConnectDependent(v)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// graphNodeOrphanModule is the graph vertex representing an orphan resource..
|
|
type graphNodeOrphanModule struct {
|
|
Path []string
|
|
|
|
dependentOn []string
|
|
}
|
|
|
|
func (n *graphNodeOrphanModule) DependableName() []string {
|
|
return []string{n.dependableName()}
|
|
}
|
|
|
|
func (n *graphNodeOrphanModule) DependentOn() []string {
|
|
return n.dependentOn
|
|
}
|
|
|
|
func (n *graphNodeOrphanModule) Name() string {
|
|
return fmt.Sprintf("%s (orphan)", n.dependableName())
|
|
}
|
|
|
|
func (n *graphNodeOrphanModule) dependableName() string {
|
|
return fmt.Sprintf("module.%s", n.Path[len(n.Path)-1])
|
|
}
|
|
|
|
// graphNodeOrphanResource is the graph vertex representing an orphan resource..
|
|
type graphNodeOrphanResource struct {
|
|
ResourceName string
|
|
|
|
dependentOn []string
|
|
}
|
|
|
|
func (n *graphNodeOrphanResource) DependableName() []string {
|
|
return []string{n.dependableName()}
|
|
}
|
|
|
|
func (n *graphNodeOrphanResource) DependentOn() []string {
|
|
return n.dependentOn
|
|
}
|
|
|
|
func (n *graphNodeOrphanResource) Name() string {
|
|
return fmt.Sprintf("%s (orphan)", n.ResourceName)
|
|
}
|
|
|
|
func (n *graphNodeOrphanResource) ProvidedBy() []string {
|
|
return []string{resourceProvider(n.ResourceName)}
|
|
}
|
|
|
|
// GraphNodeEvalable impl.
|
|
/*
|
|
func (n *graphNodeOrphanResource) EvalTree() EvalNode {
|
|
return &EvalSequence{
|
|
Nodes: []EvalNode{
|
|
&EvalRefresh{},
|
|
&EvalDiff{},
|
|
&EvalApply{},
|
|
&EvalCommitState{},
|
|
},
|
|
}
|
|
}
|
|
*/
|
|
|
|
func (n *graphNodeOrphanResource) dependableName() string {
|
|
return n.ResourceName
|
|
}
|