diff --git a/terraform/transform_orphan.go b/terraform/transform_orphan.go index a0ddd041f..8599113ec 100644 --- a/terraform/transform_orphan.go +++ b/terraform/transform_orphan.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/hashicorp/terraform/config" + "github.com/hashicorp/terraform/dag" ) // OrphanTransformer is a GraphTransformer that adds orphans to the @@ -31,9 +32,19 @@ func (t *OrphanTransformer) Transform(g *Graph) error { state.Resources[k].Dependencies) } - // Go over each module orphan and add it to the graph - for _, path := range t.State.ModuleOrphans(g.Path, t.Config) { - g.Add(&graphNodeOrphanModule{Path: path}) + // 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, t.Config) + moduleVertexes := make([]dag.Vertex, len(moduleOrphans)) + moduleStates := make([]*ModuleState, len(moduleVertexes)) + for i, path := range moduleOrphans { + moduleVertexes[i] = g.Add(&graphNodeOrphanModule{Path: path}) + moduleStates[i] = t.State.ModuleByPath(path) + } + + // Module dependencies + for i, v := range moduleVertexes { + g.ConnectTo(v, moduleStates[i].Dependencies) } return nil diff --git a/terraform/transform_orphan_test.go b/terraform/transform_orphan_test.go index c543f4c43..98c063c1a 100644 --- a/terraform/transform_orphan_test.go +++ b/terraform/transform_orphan_test.go @@ -102,6 +102,60 @@ func TestOrphanTransformer_modules(t *testing.T) { } } +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 := &ConfigTransformer{Module: mod} + if err := tf.Transform(&g); err != nil { + t.Fatalf("err: %s", err) + } + } + + transform := &OrphanTransformer{State: state, Config: mod.Config()} + 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_resourceDepends(t *testing.T) { mod := testModule(t, "transform-orphan-basic") state := &State{ @@ -161,6 +215,12 @@ aws_instance.foo module.foo (orphan) ` +const testTransformOrphanModulesDepsStr = ` +aws_instance.foo +module.foo (orphan) + aws_instance.foo +` + const testTransformOrphanResourceDependsStr = ` aws_instance.db (orphan) aws_instance.web