terraform: module orphans are properly expanded and planned for destroy
This commit is contained in:
parent
ce37165c06
commit
e45308fa6d
|
@ -204,8 +204,7 @@ func TestContext2Plan_moduleMultiVar(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func TestContext2Plan_moduleOrphans(t *testing.T) {
|
||||||
func TestContextPlan_moduleOrphans(t *testing.T) {
|
|
||||||
m := testModule(t, "plan-modules-remove")
|
m := testModule(t, "plan-modules-remove")
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
p.DiffFn = testDiffFn
|
p.DiffFn = testDiffFn
|
||||||
|
@ -224,7 +223,7 @@ func TestContextPlan_moduleOrphans(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
ctx := testContext(t, &ContextOpts{
|
ctx := testContext2(t, &ContextOpts{
|
||||||
Module: m,
|
Module: m,
|
||||||
Providers: map[string]ResourceProviderFactory{
|
Providers: map[string]ResourceProviderFactory{
|
||||||
"aws": testProviderFuncFixed(p),
|
"aws": testProviderFuncFixed(p),
|
||||||
|
@ -244,6 +243,7 @@ func TestContextPlan_moduleOrphans(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func TestContextPlan_moduleProviderInherit(t *testing.T) {
|
func TestContextPlan_moduleProviderInherit(t *testing.T) {
|
||||||
var l sync.Mutex
|
var l sync.Mutex
|
||||||
var calls []string
|
var calls []string
|
||||||
|
|
|
@ -96,6 +96,56 @@ func (n *EvalDiff) Type() EvalType {
|
||||||
return EvalTypeInstanceState
|
return EvalTypeInstanceState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EvalDiffDestroy is an EvalNode implementation that returns a plain
|
||||||
|
// destroy diff.
|
||||||
|
type EvalDiffDestroy struct {
|
||||||
|
Info *InstanceInfo
|
||||||
|
State EvalNode
|
||||||
|
Output *InstanceDiff
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *EvalDiffDestroy) Args() ([]EvalNode, []EvalType) {
|
||||||
|
return []EvalNode{n.State}, []EvalType{EvalTypeInstanceState}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test
|
||||||
|
func (n *EvalDiffDestroy) Eval(
|
||||||
|
ctx EvalContext, args []interface{}) (interface{}, error) {
|
||||||
|
// Extract our arguments
|
||||||
|
var state *InstanceState
|
||||||
|
if args[0] != nil {
|
||||||
|
state = args[0].(*InstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call pre-diff hook
|
||||||
|
err := ctx.Hook(func(h Hook) (HookAction, error) {
|
||||||
|
return h.PreDiff(n.Info, state)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The diff
|
||||||
|
diff := &InstanceDiff{Destroy: true}
|
||||||
|
|
||||||
|
// Call post-diff hook
|
||||||
|
err = ctx.Hook(func(h Hook) (HookAction, error) {
|
||||||
|
return h.PostDiff(n.Info, diff)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update our output
|
||||||
|
*n.Output = *diff
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *EvalDiffDestroy) Type() EvalType {
|
||||||
|
return EvalTypeNull
|
||||||
|
}
|
||||||
|
|
||||||
// EvalWriteDiff is an EvalNode implementation that writes the diff to
|
// EvalWriteDiff is an EvalNode implementation that writes the diff to
|
||||||
// the full diff.
|
// the full diff.
|
||||||
type EvalWriteDiff struct {
|
type EvalWriteDiff struct {
|
||||||
|
|
|
@ -105,8 +105,10 @@ func (s *State) ModuleByPath(path []string) *ModuleState {
|
||||||
// to return the actual state.
|
// to return the actual state.
|
||||||
func (s *State) ModuleOrphans(path []string, c *config.Config) [][]string {
|
func (s *State) ModuleOrphans(path []string, c *config.Config) [][]string {
|
||||||
childrenKeys := make(map[string]struct{})
|
childrenKeys := make(map[string]struct{})
|
||||||
for _, m := range c.Modules {
|
if c != nil {
|
||||||
childrenKeys[m.Name] = struct{}{}
|
for _, m := range c.Modules {
|
||||||
|
childrenKeys[m.Name] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go over the direct children and find any that aren't in our
|
// Go over the direct children and find any that aren't in our
|
||||||
|
@ -301,12 +303,14 @@ func (m *ModuleState) Orphans(c *config.Config) []string {
|
||||||
keys[k] = struct{}{}
|
keys[k] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range c.Resources {
|
if c != nil {
|
||||||
delete(keys, r.Id())
|
for _, r := range c.Resources {
|
||||||
|
delete(keys, r.Id())
|
||||||
|
|
||||||
for k, _ := range keys {
|
for k, _ := range keys {
|
||||||
if strings.HasPrefix(k, r.Id()+".") {
|
if strings.HasPrefix(k, r.Id()+".") {
|
||||||
delete(keys, k)
|
delete(keys, k)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,32 @@ func TestStateModuleOrphans(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStateModuleOrphans_nilConfig(t *testing.T) {
|
||||||
|
state := &State{
|
||||||
|
Modules: []*ModuleState{
|
||||||
|
&ModuleState{
|
||||||
|
Path: RootModulePath,
|
||||||
|
},
|
||||||
|
&ModuleState{
|
||||||
|
Path: []string{RootModuleName, "foo"},
|
||||||
|
},
|
||||||
|
&ModuleState{
|
||||||
|
Path: []string{RootModuleName, "bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := state.ModuleOrphans(RootModulePath, nil)
|
||||||
|
expected := [][]string{
|
||||||
|
[]string{RootModuleName, "foo"},
|
||||||
|
[]string{RootModuleName, "bar"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Fatalf("bad: %#v", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestInstanceState_MergeDiff(t *testing.T) {
|
func TestInstanceState_MergeDiff(t *testing.T) {
|
||||||
is := InstanceState{
|
is := InstanceState{
|
||||||
ID: "foo",
|
ID: "foo",
|
||||||
|
|
|
@ -29,8 +29,7 @@ func (t *ConfigTransformer) Transform(g *Graph) error {
|
||||||
// Get the module we care about
|
// Get the module we care about
|
||||||
module := t.Module.Child(g.Path[1:])
|
module := t.Module.Child(g.Path[1:])
|
||||||
if module == nil {
|
if module == nil {
|
||||||
return fmt.Errorf(
|
return nil
|
||||||
"module not found for path: %#v", g.Path[1:])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the configuration for this module
|
// Get the configuration for this module
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/dag"
|
"github.com/hashicorp/terraform/dag"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,5 +43,19 @@ func (t *ExpandTransform) Transform(v dag.Vertex) (dag.Vertex, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand the subgraph!
|
// Expand the subgraph!
|
||||||
|
log.Printf("[DEBUG] vertex %s: static expanding", dag.VertexName(ev))
|
||||||
return ev.Expand(t.Builder)
|
return ev.Expand(t.Builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GraphNodeBasicSubgraph struct {
|
||||||
|
NameValue string
|
||||||
|
Graph *Graph
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *GraphNodeBasicSubgraph) Name() string {
|
||||||
|
return n.NameValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *GraphNodeBasicSubgraph) Subgraph() *Graph {
|
||||||
|
return n.Graph
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package terraform
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/config"
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
"github.com/hashicorp/terraform/dag"
|
"github.com/hashicorp/terraform/dag"
|
||||||
)
|
)
|
||||||
|
@ -20,13 +21,10 @@ type OrphanTransformer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *OrphanTransformer) Transform(g *Graph) error {
|
func (t *OrphanTransformer) Transform(g *Graph) error {
|
||||||
module := t.Module.Child(g.Path[1:])
|
var config *config.Config
|
||||||
if module == nil {
|
if module := t.Module.Child(g.Path[1:]); module != nil {
|
||||||
panic(fmt.Sprintf(
|
config = module.Config()
|
||||||
"module not found for path: %#v",
|
|
||||||
g.Path[1:]))
|
|
||||||
}
|
}
|
||||||
config := module.Config()
|
|
||||||
|
|
||||||
var resourceVertexes []dag.Vertex
|
var resourceVertexes []dag.Vertex
|
||||||
if state := t.State.ModuleByPath(g.Path); state != nil {
|
if state := t.State.ModuleByPath(g.Path); state != nil {
|
||||||
|
|
Loading…
Reference in New Issue