opentofu/terraform/transform_orphan.go
2015-02-19 12:07:59 -08:00

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
}