opentofu/terraform/transform_orphan_test.go
Paul Hinze a0d3245ee3 core: Orphan addressing / targeting
Instead of trying to skip non-targeted orphans as they are added to
the graph in OrphanTransformer, remove knowledge of targeting from
OrphanTransformer and instead make the orphan resource nodes properly
addressable.

That allows us to use existing logic in TargetTransformer to filter out
the nodes appropriately. This does require adding TargetTransformer to the
list of transforms that run during DynamicExpand so that targeting can
be applied to nodes with expanded counts.

Fixes #4515
Fixes #2538
Fixes #4462
2016-01-19 17:48:44 -06:00

390 lines
8.6 KiB
Go

package terraform
import (
"strings"
"testing"
"github.com/hashicorp/terraform/dag"
)
func TestOrphanTransformer(t *testing.T) {
mod := testModule(t, "transform-orphan-basic")
state := &State{
Modules: []*ModuleState{
&ModuleState{
Path: RootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.web": &ResourceState{
Type: "aws_instance",
Primary: &InstanceState{
ID: "foo",
},
},
// The orphan
"aws_instance.db": &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, Module: mod}
if err := transform.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testTransformOrphanBasicStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
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, Module: mod}
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_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, Module: mod}
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_modulesDepsOrphan(t *testing.T) {
mod := testModule(t, "transform-orphan-modules")
state := &State{
Modules: []*ModuleState{
&ModuleState{
Path: RootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.web": &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.web",
},
},
},
}
g := Graph{Path: RootModulePath}
{
tf := &ConfigTransformer{Module: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
transform := &OrphanTransformer{State: state, Module: mod}
if err := transform.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testTransformOrphanModulesDepsOrphanStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
func TestOrphanTransformer_modulesNoRoot(t *testing.T) {
mod := testModule(t, "transform-orphan-modules")
state := &State{
Modules: []*ModuleState{
// 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, Module: mod}
if err := transform.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testTransformOrphanModulesNoRootStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
func TestOrphanTransformer_resourceDepends(t *testing.T) {
mod := testModule(t, "transform-orphan-basic")
state := &State{
Modules: []*ModuleState{
&ModuleState{
Path: RootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.web": &ResourceState{
Type: "aws_instance",
Primary: &InstanceState{
ID: "foo",
},
},
// The orphan
"aws_instance.db": &ResourceState{
Type: "aws_instance",
Primary: &InstanceState{
ID: "foo",
},
Dependencies: []string{
"aws_instance.web",
},
},
},
},
},
}
g := Graph{Path: RootModulePath}
{
tf := &ConfigTransformer{Module: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
transform := &OrphanTransformer{State: state, Module: mod}
if err := transform.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testTransformOrphanResourceDependsStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
func TestOrphanTransformer_nilState(t *testing.T) {
mod := testModule(t, "transform-orphan-basic")
g := Graph{Path: RootModulePath}
{
tf := &ConfigTransformer{Module: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
transform := &OrphanTransformer{State: nil, Module: mod}
if err := transform.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testTransformOrphanNilStateStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
func TestGraphNodeOrphanModule_impl(t *testing.T) {
var _ dag.Vertex = new(graphNodeOrphanModule)
var _ dag.NamedVertex = new(graphNodeOrphanModule)
var _ GraphNodeExpandable = new(graphNodeOrphanModule)
}
func TestGraphNodeOrphanResource_impl(t *testing.T) {
var _ dag.Vertex = new(graphNodeOrphanResource)
var _ dag.NamedVertex = new(graphNodeOrphanResource)
var _ GraphNodeProviderConsumer = new(graphNodeOrphanResource)
var _ GraphNodeAddressable = new(graphNodeOrphanResource)
}
func TestGraphNodeOrphanResource_ProvidedBy(t *testing.T) {
n := &graphNodeOrphanResource{ResourceKey: &ResourceStateKey{Type: "aws_instance"}}
if v := n.ProvidedBy(); v[0] != "aws" {
t.Fatalf("bad: %#v", v)
}
}
func TestGraphNodeOrphanResource_ProvidedBy_alias(t *testing.T) {
n := &graphNodeOrphanResource{ResourceKey: &ResourceStateKey{Type: "aws_instance"}, Provider: "aws.bar"}
if v := n.ProvidedBy(); v[0] != "aws.bar" {
t.Fatalf("bad: %#v", v)
}
}
const testTransformOrphanBasicStr = `
aws_instance.db (orphan)
aws_instance.web
`
const testTransformOrphanModulesStr = `
aws_instance.foo
module.foo (orphan)
`
const testTransformOrphanModulesDepsStr = `
aws_instance.foo
module.foo (orphan)
aws_instance.foo
`
const testTransformOrphanModulesDepsOrphanStr = `
aws_instance.foo
aws_instance.web (orphan)
module.foo (orphan)
aws_instance.web (orphan)
`
const testTransformOrphanNilStateStr = `
aws_instance.web
`
const testTransformOrphanResourceDependsStr = `
aws_instance.db (orphan)
aws_instance.web
aws_instance.web
`
const testTransformOrphanModulesNoRootStr = `
aws_instance.foo
module.foo (orphan)
`