terraform: module orphans are properly expanded and planned for destroy

This commit is contained in:
Mitchell Hashimoto 2015-02-11 17:47:30 -08:00
parent ce37165c06
commit e45308fa6d
7 changed files with 111 additions and 18 deletions

View File

@ -204,8 +204,7 @@ func TestContext2Plan_moduleMultiVar(t *testing.T) {
}
}
/*
func TestContextPlan_moduleOrphans(t *testing.T) {
func TestContext2Plan_moduleOrphans(t *testing.T) {
m := testModule(t, "plan-modules-remove")
p := testProvider("aws")
p.DiffFn = testDiffFn
@ -224,7 +223,7 @@ func TestContextPlan_moduleOrphans(t *testing.T) {
},
},
}
ctx := testContext(t, &ContextOpts{
ctx := testContext2(t, &ContextOpts{
Module: m,
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
@ -244,6 +243,7 @@ func TestContextPlan_moduleOrphans(t *testing.T) {
}
}
/*
func TestContextPlan_moduleProviderInherit(t *testing.T) {
var l sync.Mutex
var calls []string

View File

@ -96,6 +96,56 @@ func (n *EvalDiff) Type() EvalType {
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
// the full diff.
type EvalWriteDiff struct {

View File

@ -105,9 +105,11 @@ func (s *State) ModuleByPath(path []string) *ModuleState {
// to return the actual state.
func (s *State) ModuleOrphans(path []string, c *config.Config) [][]string {
childrenKeys := make(map[string]struct{})
if c != nil {
for _, m := range c.Modules {
childrenKeys[m.Name] = struct{}{}
}
}
// Go over the direct children and find any that aren't in our
// keys.
@ -301,6 +303,7 @@ func (m *ModuleState) Orphans(c *config.Config) []string {
keys[k] = struct{}{}
}
if c != nil {
for _, r := range c.Resources {
delete(keys, r.Id())
@ -310,6 +313,7 @@ func (m *ModuleState) Orphans(c *config.Config) []string {
}
}
}
}
result := make([]string, 0, len(keys))
for k, _ := range keys {

View File

@ -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) {
is := InstanceState{
ID: "foo",

View File

@ -29,8 +29,7 @@ func (t *ConfigTransformer) Transform(g *Graph) error {
// Get the module we care about
module := t.Module.Child(g.Path[1:])
if module == nil {
return fmt.Errorf(
"module not found for path: %#v", g.Path[1:])
return nil
}
// Get the configuration for this module

View File

@ -1,6 +1,8 @@
package terraform
import (
"log"
"github.com/hashicorp/terraform/dag"
)
@ -41,5 +43,19 @@ func (t *ExpandTransform) Transform(v dag.Vertex) (dag.Vertex, error) {
}
// Expand the subgraph!
log.Printf("[DEBUG] vertex %s: static expanding", dag.VertexName(ev))
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
}

View File

@ -3,6 +3,7 @@ package terraform
import (
"fmt"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/config/module"
"github.com/hashicorp/terraform/dag"
)
@ -20,13 +21,10 @@ type OrphanTransformer struct {
}
func (t *OrphanTransformer) Transform(g *Graph) error {
module := t.Module.Child(g.Path[1:])
if module == nil {
panic(fmt.Sprintf(
"module not found for path: %#v",
g.Path[1:]))
var config *config.Config
if module := t.Module.Child(g.Path[1:]); module != nil {
config = module.Config()
}
config := module.Config()
var resourceVertexes []dag.Vertex
if state := t.State.ModuleByPath(g.Path); state != nil {