2015-01-26 22:17:52 -06:00
|
|
|
package terraform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2015-01-30 15:31:39 -06:00
|
|
|
"github.com/hashicorp/terraform/config/module"
|
2015-01-27 13:10:51 -06:00
|
|
|
"github.com/hashicorp/terraform/dag"
|
2015-01-26 22:17:52 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
// OrphanTransformer is a GraphTransformer that adds orphans to the
|
|
|
|
// graph. This transformer adds both resource and module orphans.
|
|
|
|
type OrphanTransformer struct {
|
2015-01-26 23:32:32 -06:00
|
|
|
// State is the global state. We require the global state to
|
|
|
|
// properly find module orphans at our path.
|
|
|
|
State *State
|
|
|
|
|
2015-01-30 15:31:39 -06:00
|
|
|
// Module is the root module. We'll look up the proper configuration
|
|
|
|
// using the graph path.
|
|
|
|
Module *module.Tree
|
2015-01-26 22:17:52 -06:00
|
|
|
}
|
|
|
|
|
2015-01-26 23:23:27 -06:00
|
|
|
func (t *OrphanTransformer) Transform(g *Graph) error {
|
2015-01-26 23:32:32 -06:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2015-01-30 15:31:39 -06:00
|
|
|
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()
|
|
|
|
|
2015-01-27 13:00:24 -06:00
|
|
|
// Go over each resource orphan and add it to the graph.
|
2015-01-30 15:31:39 -06:00
|
|
|
resourceOrphans := state.Orphans(config)
|
2015-01-27 13:18:17 -06:00
|
|
|
resourceVertexes := make([]dag.Vertex, len(resourceOrphans))
|
|
|
|
for i, k := range resourceOrphans {
|
2015-01-27 16:56:01 -06:00
|
|
|
resourceVertexes[i] = g.Add(&graphNodeOrphanResource{
|
|
|
|
ResourceName: k,
|
|
|
|
dependentOn: state.Resources[k].Dependencies,
|
|
|
|
})
|
2015-01-26 22:17:52 -06:00
|
|
|
}
|
|
|
|
|
2015-01-27 13:10:51 -06:00
|
|
|
// 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.
|
2015-01-30 15:31:39 -06:00
|
|
|
moduleOrphans := t.State.ModuleOrphans(g.Path, config)
|
2015-01-27 13:10:51 -06:00
|
|
|
moduleVertexes := make([]dag.Vertex, len(moduleOrphans))
|
|
|
|
for i, path := range moduleOrphans {
|
2015-01-27 16:56:01 -06:00
|
|
|
moduleVertexes[i] = g.Add(&graphNodeOrphanModule{
|
|
|
|
Path: path,
|
|
|
|
dependentOn: t.State.ModuleByPath(path).Dependencies,
|
|
|
|
})
|
2015-01-27 13:10:51 -06:00
|
|
|
}
|
|
|
|
|
2015-01-27 13:18:17 -06:00
|
|
|
// 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
|
2015-01-27 16:56:01 -06:00
|
|
|
for _, v := range resourceVertexes {
|
|
|
|
g.ConnectDependent(v)
|
2015-01-27 13:18:17 -06:00
|
|
|
}
|
|
|
|
|
2015-01-27 13:10:51 -06:00
|
|
|
// Module dependencies
|
2015-01-27 16:56:01 -06:00
|
|
|
for _, v := range moduleVertexes {
|
|
|
|
g.ConnectDependent(v)
|
2015-01-27 13:00:24 -06:00
|
|
|
}
|
2015-01-26 22:17:52 -06:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-01-27 13:00:24 -06:00
|
|
|
// graphNodeOrphanModule is the graph vertex representing an orphan resource..
|
|
|
|
type graphNodeOrphanModule struct {
|
|
|
|
Path []string
|
2015-01-27 16:56:01 -06:00
|
|
|
|
|
|
|
dependentOn []string
|
2015-01-27 13:00:24 -06:00
|
|
|
}
|
|
|
|
|
2015-01-27 15:44:27 -06:00
|
|
|
func (n *graphNodeOrphanModule) DependableName() []string {
|
|
|
|
return []string{n.dependableName()}
|
|
|
|
}
|
|
|
|
|
2015-01-27 16:56:01 -06:00
|
|
|
func (n *graphNodeOrphanModule) DependentOn() []string {
|
|
|
|
return n.dependentOn
|
|
|
|
}
|
|
|
|
|
2015-01-27 13:00:24 -06:00
|
|
|
func (n *graphNodeOrphanModule) Name() string {
|
2015-01-27 15:44:27 -06:00
|
|
|
return fmt.Sprintf("%s (orphan)", n.dependableName())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *graphNodeOrphanModule) dependableName() string {
|
|
|
|
return fmt.Sprintf("module.%s", n.Path[len(n.Path)-1])
|
2015-01-27 13:00:24 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// graphNodeOrphanResource is the graph vertex representing an orphan resource..
|
2015-01-26 22:17:52 -06:00
|
|
|
type graphNodeOrphanResource struct {
|
|
|
|
ResourceName string
|
2015-01-27 16:56:01 -06:00
|
|
|
|
|
|
|
dependentOn []string
|
2015-01-26 22:17:52 -06:00
|
|
|
}
|
|
|
|
|
2015-01-27 15:44:27 -06:00
|
|
|
func (n *graphNodeOrphanResource) DependableName() []string {
|
|
|
|
return []string{n.dependableName()}
|
|
|
|
}
|
|
|
|
|
2015-01-27 16:56:01 -06:00
|
|
|
func (n *graphNodeOrphanResource) DependentOn() []string {
|
|
|
|
return n.dependentOn
|
|
|
|
}
|
|
|
|
|
2015-01-26 22:17:52 -06:00
|
|
|
func (n *graphNodeOrphanResource) Name() string {
|
|
|
|
return fmt.Sprintf("%s (orphan)", n.ResourceName)
|
|
|
|
}
|
2015-01-27 15:44:27 -06:00
|
|
|
|
2015-02-10 01:32:28 -06:00
|
|
|
func (n *graphNodeOrphanResource) ProvidedBy() []string {
|
|
|
|
return []string{resourceProvider(n.ResourceName)}
|
2015-01-28 00:00:56 -06:00
|
|
|
}
|
|
|
|
|
2015-02-03 19:46:11 -06:00
|
|
|
// GraphNodeEvalable impl.
|
2015-02-04 19:02:18 -06:00
|
|
|
/*
|
2015-02-03 19:46:11 -06:00
|
|
|
func (n *graphNodeOrphanResource) EvalTree() EvalNode {
|
|
|
|
return &EvalSequence{
|
|
|
|
Nodes: []EvalNode{
|
|
|
|
&EvalRefresh{},
|
|
|
|
&EvalDiff{},
|
|
|
|
&EvalApply{},
|
|
|
|
&EvalCommitState{},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2015-02-04 19:02:18 -06:00
|
|
|
*/
|
2015-02-03 19:46:11 -06:00
|
|
|
|
2015-01-27 15:44:27 -06:00
|
|
|
func (n *graphNodeOrphanResource) dependableName() string {
|
|
|
|
return n.ResourceName
|
|
|
|
}
|