diff --git a/terraform/test-fixtures/transform-orphan-modules/main.tf b/terraform/test-fixtures/transform-orphan-modules/main.tf new file mode 100644 index 000000000..919f140bb --- /dev/null +++ b/terraform/test-fixtures/transform-orphan-modules/main.tf @@ -0,0 +1 @@ +resource "aws_instance" "foo" {} diff --git a/terraform/transform_orphan.go b/terraform/transform_orphan.go index 66e4fa8ac..a0ddd041f 100644 --- a/terraform/transform_orphan.go +++ b/terraform/transform_orphan.go @@ -24,25 +24,31 @@ func (t *OrphanTransformer) Transform(g *Graph) error { return nil } - // Get the orphans from our configuration. This will only get resources. - orphans := state.Orphans(t.Config) - if len(orphans) == 0 { - return nil - } - - // Go over each orphan and add it to the graph. - for _, k := range orphans { + // Go over each resource orphan and add it to the graph. + for _, k := range state.Orphans(t.Config) { g.ConnectTo( g.Add(&graphNodeOrphanResource{ResourceName: k}), state.Resources[k].Dependencies) } - // TODO: modules + // 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}) + } return nil } -// graphNodeOrphan is the graph vertex representing an orphan resource.. +// graphNodeOrphanModule is the graph vertex representing an orphan resource.. +type graphNodeOrphanModule struct { + Path []string +} + +func (n *graphNodeOrphanModule) Name() string { + return fmt.Sprintf("module.%s (orphan)", n.Path[len(n.Path)-1]) +} + +// graphNodeOrphanResource is the graph vertex representing an orphan resource.. type graphNodeOrphanResource struct { ResourceName string } diff --git a/terraform/transform_orphan_test.go b/terraform/transform_orphan_test.go index 299455e0f..c543f4c43 100644 --- a/terraform/transform_orphan_test.go +++ b/terraform/transform_orphan_test.go @@ -51,6 +51,57 @@ func TestOrphanTransformer(t *testing.T) { } } +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 := &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(testTransformOrphanModulesStr) + if actual != expected { + t.Fatalf("bad:\n\n%s", actual) + } +} + func TestOrphanTransformer_resourceDepends(t *testing.T) { mod := testModule(t, "transform-orphan-basic") state := &State{ @@ -105,6 +156,11 @@ aws_instance.db (orphan) aws_instance.web ` +const testTransformOrphanModulesStr = ` +aws_instance.foo +module.foo (orphan) +` + const testTransformOrphanResourceDependsStr = ` aws_instance.db (orphan) aws_instance.web