terraform: remove old orphan transform
This commit is contained in:
parent
9426b71a5f
commit
4e4d51e6ba
|
@ -165,15 +165,6 @@ func (n *GraphNodeConfigResource) DynamicExpand(ctx EvalContext) (*Graph, error)
|
|||
|
||||
// Additional destroy modifications.
|
||||
if n.Destroy {
|
||||
// If we're destroying a primary or tainted resource, we want to
|
||||
// expand orphans, which have all the same semantics in a destroy
|
||||
// as a primary or tainted resource.
|
||||
steps = append(steps, &OrphanTransformer{
|
||||
Resource: n.Resource,
|
||||
State: state,
|
||||
View: n.Resource.Id(),
|
||||
})
|
||||
|
||||
steps = append(steps, &DeposedTransformer{
|
||||
State: state,
|
||||
View: n.Resource.Id(),
|
||||
|
|
|
@ -1,437 +0,0 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
// GraphNodeStateRepresentative is an interface that can be implemented by
|
||||
// a node to say that it is representing a resource in the state.
|
||||
type GraphNodeStateRepresentative interface {
|
||||
StateId() []string
|
||||
}
|
||||
|
||||
// OrphanTransformer is a GraphTransformer that adds orphans to the
|
||||
// graph. This transformer adds both resource and module orphans.
|
||||
type OrphanTransformer struct {
|
||||
// Resource is resource configuration. This is only non-nil when
|
||||
// expanding a resource that is in the configuration. It can't be
|
||||
// dependend on.
|
||||
Resource *config.Resource
|
||||
|
||||
// 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
|
||||
|
||||
// View, if non-nil will set a view on the module state.
|
||||
View string
|
||||
}
|
||||
|
||||
func (t *OrphanTransformer) Transform(g *Graph) error {
|
||||
if t.State == nil {
|
||||
// If the entire state is nil, there can't be any orphans
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build up all our state representatives
|
||||
resourceRep := make(map[string]struct{})
|
||||
for _, v := range g.Vertices() {
|
||||
if sr, ok := v.(GraphNodeStateRepresentative); ok {
|
||||
for _, k := range sr.StateId() {
|
||||
resourceRep[k] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var config *config.Config
|
||||
if t.Module != nil {
|
||||
if module := t.Module.Child(g.Path[1:]); module != nil {
|
||||
config = module.Config()
|
||||
}
|
||||
}
|
||||
|
||||
var resourceVertexes []dag.Vertex
|
||||
if state := t.State.ModuleByPath(g.Path); state != nil {
|
||||
// If we have state, then we can have orphan resources
|
||||
|
||||
// If we have a view, get the view
|
||||
if t.View != "" {
|
||||
state = state.View(t.View)
|
||||
}
|
||||
|
||||
resourceOrphans := state.Orphans(config)
|
||||
|
||||
resourceVertexes = make([]dag.Vertex, len(resourceOrphans))
|
||||
for i, k := range resourceOrphans {
|
||||
// If this orphan is represented by some other node somehow,
|
||||
// then ignore it.
|
||||
if _, ok := resourceRep[k]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
rs := state.Resources[k]
|
||||
|
||||
rsk, err := ParseResourceStateKey(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resourceVertexes[i] = g.Add(&graphNodeOrphanResource{
|
||||
Path: g.Path,
|
||||
ResourceKey: rsk,
|
||||
Resource: t.Resource,
|
||||
Provider: rs.Provider,
|
||||
dependentOn: rs.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 {
|
||||
var deps []string
|
||||
if s := t.State.ModuleByPath(path); s != nil {
|
||||
deps = s.Dependencies
|
||||
}
|
||||
|
||||
moduleVertexes[i] = g.Add(&graphNodeOrphanModule{
|
||||
Path: path,
|
||||
dependentOn: deps,
|
||||
})
|
||||
}
|
||||
|
||||
// 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])
|
||||
}
|
||||
|
||||
// GraphNodeExpandable
|
||||
func (n *graphNodeOrphanModule) Expand(b GraphBuilder) (GraphNodeSubgraph, error) {
|
||||
g, err := b.Build(n.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &GraphNodeBasicSubgraph{
|
||||
NameValue: n.Name(),
|
||||
Graph: g,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// graphNodeOrphanResource is the graph vertex representing an orphan resource..
|
||||
type graphNodeOrphanResource struct {
|
||||
Path []string
|
||||
ResourceKey *ResourceStateKey
|
||||
Resource *config.Resource
|
||||
Provider string
|
||||
|
||||
dependentOn []string
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) ConfigType() GraphNodeConfigType {
|
||||
return GraphNodeConfigTypeResource
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) ResourceAddress() *ResourceAddress {
|
||||
return &ResourceAddress{
|
||||
Index: n.ResourceKey.Index,
|
||||
InstanceType: TypePrimary,
|
||||
Name: n.ResourceKey.Name,
|
||||
Path: n.Path[1:],
|
||||
Type: n.ResourceKey.Type,
|
||||
Mode: n.ResourceKey.Mode,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) DependableName() []string {
|
||||
return []string{n.dependableName()}
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) DependentOn() []string {
|
||||
return n.dependentOn
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) Flatten(p []string) (dag.Vertex, error) {
|
||||
return &graphNodeOrphanResourceFlat{
|
||||
graphNodeOrphanResource: n,
|
||||
PathValue: p,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) Name() string {
|
||||
return fmt.Sprintf("%s (orphan)", n.ResourceKey)
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) ProvidedBy() []string {
|
||||
return []string{resourceProvider(n.ResourceKey.Type, n.Provider)}
|
||||
}
|
||||
|
||||
// GraphNodeEvalable impl.
|
||||
func (n *graphNodeOrphanResource) EvalTree() EvalNode {
|
||||
|
||||
seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)}
|
||||
|
||||
// Build instance info
|
||||
info := &InstanceInfo{Id: n.ResourceKey.String(), Type: n.ResourceKey.Type}
|
||||
info.uniqueExtra = "destroy"
|
||||
|
||||
seq.Nodes = append(seq.Nodes, &EvalInstanceInfo{Info: info})
|
||||
|
||||
// Each resource mode has its own lifecycle
|
||||
switch n.ResourceKey.Mode {
|
||||
case config.ManagedResourceMode:
|
||||
seq.Nodes = append(
|
||||
seq.Nodes,
|
||||
n.managedResourceEvalNodes(info)...,
|
||||
)
|
||||
case config.DataResourceMode:
|
||||
seq.Nodes = append(
|
||||
seq.Nodes,
|
||||
n.dataResourceEvalNodes(info)...,
|
||||
)
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported resource mode %s", n.ResourceKey.Mode))
|
||||
}
|
||||
|
||||
return seq
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) managedResourceEvalNodes(info *InstanceInfo) []EvalNode {
|
||||
var provider ResourceProvider
|
||||
var state *InstanceState
|
||||
|
||||
nodes := make([]EvalNode, 0, 3)
|
||||
|
||||
// Refresh the resource
|
||||
nodes = append(nodes, &EvalOpFilter{
|
||||
Ops: []walkOperation{walkRefresh},
|
||||
Node: &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalReadState{
|
||||
Name: n.ResourceKey.String(),
|
||||
Output: &state,
|
||||
},
|
||||
&EvalRefresh{
|
||||
Info: info,
|
||||
Provider: &provider,
|
||||
State: &state,
|
||||
Output: &state,
|
||||
},
|
||||
&EvalWriteState{
|
||||
Name: n.ResourceKey.String(),
|
||||
ResourceType: n.ResourceKey.Type,
|
||||
Provider: n.Provider,
|
||||
Dependencies: n.DependentOn(),
|
||||
State: &state,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// Diff the resource
|
||||
var diff *InstanceDiff
|
||||
nodes = append(nodes, &EvalOpFilter{
|
||||
Ops: []walkOperation{walkPlan, walkPlanDestroy},
|
||||
Node: &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalReadState{
|
||||
Name: n.ResourceKey.String(),
|
||||
Output: &state,
|
||||
},
|
||||
&EvalDiffDestroy{
|
||||
Info: info,
|
||||
State: &state,
|
||||
Output: &diff,
|
||||
},
|
||||
&EvalCheckPreventDestroy{
|
||||
Resource: n.Resource,
|
||||
ResourceId: n.ResourceKey.String(),
|
||||
Diff: &diff,
|
||||
},
|
||||
&EvalWriteDiff{
|
||||
Name: n.ResourceKey.String(),
|
||||
Diff: &diff,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// Apply
|
||||
var err error
|
||||
nodes = append(nodes, &EvalOpFilter{
|
||||
Ops: []walkOperation{walkApply, walkDestroy},
|
||||
Node: &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalReadDiff{
|
||||
Name: n.ResourceKey.String(),
|
||||
Diff: &diff,
|
||||
},
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalReadState{
|
||||
Name: n.ResourceKey.String(),
|
||||
Output: &state,
|
||||
},
|
||||
&EvalApplyPre{
|
||||
Info: info,
|
||||
State: &state,
|
||||
Diff: &diff,
|
||||
},
|
||||
&EvalApply{
|
||||
Info: info,
|
||||
State: &state,
|
||||
Diff: &diff,
|
||||
Provider: &provider,
|
||||
Output: &state,
|
||||
Error: &err,
|
||||
},
|
||||
&EvalWriteState{
|
||||
Name: n.ResourceKey.String(),
|
||||
ResourceType: n.ResourceKey.Type,
|
||||
Provider: n.Provider,
|
||||
Dependencies: n.DependentOn(),
|
||||
State: &state,
|
||||
},
|
||||
&EvalApplyPost{
|
||||
Info: info,
|
||||
State: &state,
|
||||
Error: &err,
|
||||
},
|
||||
&EvalUpdateStateHook{},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) dataResourceEvalNodes(info *InstanceInfo) []EvalNode {
|
||||
nodes := make([]EvalNode, 0, 3)
|
||||
|
||||
// This will remain nil, since we don't retain states for orphaned
|
||||
// data resources.
|
||||
var state *InstanceState
|
||||
|
||||
// On both refresh and apply we just drop our state altogether,
|
||||
// since the config resource validation pass will have proven that the
|
||||
// resources remaining in the configuration don't need it.
|
||||
nodes = append(nodes, &EvalOpFilter{
|
||||
Ops: []walkOperation{walkRefresh, walkApply},
|
||||
Node: &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalWriteState{
|
||||
Name: n.ResourceKey.String(),
|
||||
ResourceType: n.ResourceKey.Type,
|
||||
Provider: n.Provider,
|
||||
Dependencies: n.DependentOn(),
|
||||
State: &state, // state is nil
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) dependableName() string {
|
||||
return n.ResourceKey.String()
|
||||
}
|
||||
|
||||
// GraphNodeDestroyable impl.
|
||||
func (n *graphNodeOrphanResource) DestroyNode() GraphNodeDestroy {
|
||||
return n
|
||||
}
|
||||
|
||||
// GraphNodeDestroy impl.
|
||||
func (n *graphNodeOrphanResource) CreateBeforeDestroy() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) CreateNode() dag.Vertex {
|
||||
return n
|
||||
}
|
||||
|
||||
// Same as graphNodeOrphanResource, but for flattening
|
||||
type graphNodeOrphanResourceFlat struct {
|
||||
*graphNodeOrphanResource
|
||||
|
||||
PathValue []string
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResourceFlat) Name() string {
|
||||
return fmt.Sprintf(
|
||||
"%s.%s", modulePrefixStr(n.PathValue), n.graphNodeOrphanResource.Name())
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResourceFlat) Path() []string {
|
||||
return n.PathValue
|
||||
}
|
||||
|
||||
// GraphNodeDestroyable impl.
|
||||
func (n *graphNodeOrphanResourceFlat) DestroyNode() GraphNodeDestroy {
|
||||
return n
|
||||
}
|
||||
|
||||
// GraphNodeDestroy impl.
|
||||
func (n *graphNodeOrphanResourceFlat) CreateBeforeDestroy() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResourceFlat) CreateNode() dag.Vertex {
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResourceFlat) ProvidedBy() []string {
|
||||
return modulePrefixList(
|
||||
n.graphNodeOrphanResource.ProvidedBy(),
|
||||
modulePrefixStr(n.PathValue))
|
||||
}
|
|
@ -1,389 +0,0 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
func TestOrphanTransformer(t *testing.T) {
|
||||
mod := testModule(t, "transform-orphan-basic")
|
||||
state := &State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: RootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.web": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
// The orphan
|
||||
"aws_instance.db": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
g := Graph{Path: RootModulePath}
|
||||
{
|
||||
tf := &ConfigTransformerOld{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
transform := &OrphanTransformer{State: state, Module: mod}
|
||||
if err := transform.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformOrphanBasicStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad:\n\n%s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrphanTransformer_modules(t *testing.T) {
|
||||
mod := testModule(t, "transform-orphan-modules")
|
||||
state := &State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: RootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.foo": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Orphan module
|
||||
&ModuleState{
|
||||
Path: []string{RootModuleName, "foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.web": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
g := Graph{Path: RootModulePath}
|
||||
{
|
||||
tf := &ConfigTransformerOld{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
transform := &OrphanTransformer{State: state, Module: mod}
|
||||
if err := transform.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformOrphanModulesStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad:\n\n%s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrphanTransformer_modulesDeps(t *testing.T) {
|
||||
mod := testModule(t, "transform-orphan-modules")
|
||||
state := &State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: RootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.foo": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Orphan module
|
||||
&ModuleState{
|
||||
Path: []string{RootModuleName, "foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.web": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"aws_instance.foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
g := Graph{Path: RootModulePath}
|
||||
{
|
||||
tf := &ConfigTransformerOld{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
transform := &OrphanTransformer{State: state, Module: mod}
|
||||
if err := transform.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformOrphanModulesDepsStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad:\n\n%s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrphanTransformer_modulesDepsOrphan(t *testing.T) {
|
||||
mod := testModule(t, "transform-orphan-modules")
|
||||
state := &State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: RootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.web": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Orphan module
|
||||
&ModuleState{
|
||||
Path: []string{RootModuleName, "foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.web": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"aws_instance.web",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
g := Graph{Path: RootModulePath}
|
||||
{
|
||||
tf := &ConfigTransformerOld{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
transform := &OrphanTransformer{State: state, Module: mod}
|
||||
if err := transform.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformOrphanModulesDepsOrphanStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad:\n\n%s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrphanTransformer_modulesNoRoot(t *testing.T) {
|
||||
mod := testModule(t, "transform-orphan-modules")
|
||||
state := &State{
|
||||
Modules: []*ModuleState{
|
||||
// Orphan module
|
||||
&ModuleState{
|
||||
Path: []string{RootModuleName, "foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.web": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
g := Graph{Path: RootModulePath}
|
||||
{
|
||||
tf := &ConfigTransformerOld{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
transform := &OrphanTransformer{State: state, Module: mod}
|
||||
if err := transform.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformOrphanModulesNoRootStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad:\n\n%s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrphanTransformer_resourceDepends(t *testing.T) {
|
||||
mod := testModule(t, "transform-orphan-basic")
|
||||
state := &State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: RootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.web": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
// The orphan
|
||||
"aws_instance.db": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
Dependencies: []string{
|
||||
"aws_instance.web",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
g := Graph{Path: RootModulePath}
|
||||
{
|
||||
tf := &ConfigTransformerOld{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
transform := &OrphanTransformer{State: state, Module: mod}
|
||||
if err := transform.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformOrphanResourceDependsStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad:\n\n%s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrphanTransformer_nilState(t *testing.T) {
|
||||
mod := testModule(t, "transform-orphan-basic")
|
||||
|
||||
g := Graph{Path: RootModulePath}
|
||||
{
|
||||
tf := &ConfigTransformerOld{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
transform := &OrphanTransformer{State: nil, Module: mod}
|
||||
if err := transform.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformOrphanNilStateStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad:\n\n%s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGraphNodeOrphanModule_impl(t *testing.T) {
|
||||
var _ dag.Vertex = new(graphNodeOrphanModule)
|
||||
var _ dag.NamedVertex = new(graphNodeOrphanModule)
|
||||
var _ GraphNodeExpandable = new(graphNodeOrphanModule)
|
||||
}
|
||||
|
||||
func TestGraphNodeOrphanResource_impl(t *testing.T) {
|
||||
var _ dag.Vertex = new(graphNodeOrphanResource)
|
||||
var _ dag.NamedVertex = new(graphNodeOrphanResource)
|
||||
var _ GraphNodeProviderConsumer = new(graphNodeOrphanResource)
|
||||
var _ GraphNodeAddressable = new(graphNodeOrphanResource)
|
||||
}
|
||||
|
||||
func TestGraphNodeOrphanResource_ProvidedBy(t *testing.T) {
|
||||
n := &graphNodeOrphanResource{ResourceKey: &ResourceStateKey{Type: "aws_instance"}}
|
||||
if v := n.ProvidedBy(); v[0] != "aws" {
|
||||
t.Fatalf("bad: %#v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGraphNodeOrphanResource_ProvidedBy_alias(t *testing.T) {
|
||||
n := &graphNodeOrphanResource{ResourceKey: &ResourceStateKey{Type: "aws_instance"}, Provider: "aws.bar"}
|
||||
if v := n.ProvidedBy(); v[0] != "aws.bar" {
|
||||
t.Fatalf("bad: %#v", v)
|
||||
}
|
||||
}
|
||||
|
||||
const testTransformOrphanBasicStr = `
|
||||
aws_instance.db (orphan)
|
||||
aws_instance.web
|
||||
`
|
||||
|
||||
const testTransformOrphanModulesStr = `
|
||||
aws_instance.foo
|
||||
module.foo (orphan)
|
||||
`
|
||||
|
||||
const testTransformOrphanModulesDepsStr = `
|
||||
aws_instance.foo
|
||||
module.foo (orphan)
|
||||
aws_instance.foo
|
||||
`
|
||||
|
||||
const testTransformOrphanModulesDepsOrphanStr = `
|
||||
aws_instance.foo
|
||||
aws_instance.web (orphan)
|
||||
module.foo (orphan)
|
||||
aws_instance.web (orphan)
|
||||
`
|
||||
|
||||
const testTransformOrphanNilStateStr = `
|
||||
aws_instance.web
|
||||
`
|
||||
|
||||
const testTransformOrphanResourceDependsStr = `
|
||||
aws_instance.db (orphan)
|
||||
aws_instance.web
|
||||
aws_instance.web
|
||||
`
|
||||
|
||||
const testTransformOrphanModulesNoRootStr = `
|
||||
aws_instance.foo
|
||||
module.foo (orphan)
|
||||
`
|
Loading…
Reference in New Issue