opentofu/terraform/transform_orphan_resource_test.go
Kristin Laemmert 47a16b0937
addrs: embed Provider in AbsProviderConfig instead of Type
a large refactor to addrs.AbsProviderConfig, embedding the addrs.Provider instead of a Type string. I've added and updated tests, added some Legacy functions to support older state formats and shims, and added a normalization step when reading v4 (current) state files (not the added tests under states/statefile/roundtrip which work with both current and legacy-style AbsProviderConfig strings).

The remaining 'fixme' and 'todo' comments are mostly going to be addressed in a subsequent PR and involve looking up a given local provider config's FQN. This is fine for now as we are only working with default assumption.
2020-02-13 15:32:58 -05:00

307 lines
7.4 KiB
Go

package terraform
import (
"fmt"
"strings"
"testing"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/dag"
"github.com/hashicorp/terraform/states"
)
func TestOrphanResourceInstanceTransformer(t *testing.T) {
mod := testModule(t, "transform-orphan-basic")
state := states.BuildState(func(s *states.SyncState) {
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "web",
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"id": "foo",
},
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("aws"),
Module: addrs.RootModuleInstance,
},
)
// The orphan
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "db",
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"id": "foo",
},
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("aws"),
Module: addrs.RootModuleInstance,
},
)
})
g := Graph{Path: addrs.RootModuleInstance}
{
tf := &ConfigTransformer{Config: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
{
tf := &OrphanResourceInstanceTransformer{
Concrete: testOrphanResourceConcreteFunc,
State: state,
Config: mod,
}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testTransformOrphanResourceBasicStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
func TestOrphanResourceInstanceTransformer_countGood(t *testing.T) {
mod := testModule(t, "transform-orphan-count")
state := states.BuildState(func(s *states.SyncState) {
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "foo",
}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"id": "foo",
},
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("aws"),
Module: addrs.RootModuleInstance,
},
)
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "foo",
}.Instance(addrs.IntKey(1)).Absolute(addrs.RootModuleInstance),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"id": "foo",
},
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("aws"),
Module: addrs.RootModuleInstance,
},
)
})
g := Graph{Path: addrs.RootModuleInstance}
{
tf := &ConfigTransformer{Config: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
{
tf := &OrphanResourceInstanceTransformer{
Concrete: testOrphanResourceConcreteFunc,
State: state,
Config: mod,
}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testTransformOrphanResourceCountStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
func TestOrphanResourceInstanceTransformer_countBad(t *testing.T) {
mod := testModule(t, "transform-orphan-count-empty")
state := states.BuildState(func(s *states.SyncState) {
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "foo",
}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"id": "foo",
},
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("aws"),
Module: addrs.RootModuleInstance,
},
)
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "foo",
}.Instance(addrs.IntKey(1)).Absolute(addrs.RootModuleInstance),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"id": "foo",
},
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("aws"),
Module: addrs.RootModuleInstance,
},
)
})
g := Graph{Path: addrs.RootModuleInstance}
{
tf := &ConfigTransformer{Config: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
{
tf := &OrphanResourceInstanceTransformer{
Concrete: testOrphanResourceConcreteFunc,
State: state,
Config: mod,
}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testTransformOrphanResourceCountBadStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
func TestOrphanResourceInstanceTransformer_modules(t *testing.T) {
mod := testModule(t, "transform-orphan-modules")
state := states.BuildState(func(s *states.SyncState) {
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "foo",
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"id": "foo",
},
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("aws"),
Module: addrs.RootModuleInstance,
},
)
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "web",
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("child", addrs.NoKey)),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"id": "foo",
},
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("aws"),
Module: addrs.RootModuleInstance,
},
)
})
g := Graph{Path: addrs.RootModuleInstance}
{
tf := &ConfigTransformer{Config: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
{
tf := &OrphanResourceInstanceTransformer{
Concrete: testOrphanResourceConcreteFunc,
State: state,
Config: mod,
}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
got := strings.TrimSpace(g.String())
want := strings.TrimSpace(testTransformOrphanResourceModulesStr)
if got != want {
t.Fatalf("wrong state result\ngot:\n%s\n\nwant:\n%s", got, want)
}
}
const testTransformOrphanResourceBasicStr = `
aws_instance.db (orphan)
aws_instance.web
`
const testTransformOrphanResourceCountStr = `
aws_instance.foo
`
const testTransformOrphanResourceCountBadStr = `
aws_instance.foo[0] (orphan)
aws_instance.foo[1] (orphan)
`
const testTransformOrphanResourceModulesStr = `
aws_instance.foo
module.child.aws_instance.web (orphan)
`
func testOrphanResourceConcreteFunc(a *NodeAbstractResourceInstance) dag.Vertex {
return &testOrphanResourceInstanceConcrete{a}
}
type testOrphanResourceInstanceConcrete struct {
*NodeAbstractResourceInstance
}
func (n *testOrphanResourceInstanceConcrete) Name() string {
return fmt.Sprintf("%s (orphan)", n.NodeAbstractResourceInstance.Name())
}