mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 18:01:01 -06:00
a0d3245ee3
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
332 lines
7.5 KiB
Go
332 lines
7.5 KiB
Go
package terraform
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseResourceAddress(t *testing.T) {
|
|
cases := map[string]struct {
|
|
Input string
|
|
Expected *ResourceAddress
|
|
}{
|
|
"implicit primary, no specific index": {
|
|
Input: "aws_instance.foo",
|
|
Expected: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
},
|
|
"implicit primary, explicit index": {
|
|
Input: "aws_instance.foo[2]",
|
|
Expected: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 2,
|
|
},
|
|
},
|
|
"implicit primary, explicit index over ten": {
|
|
Input: "aws_instance.foo[12]",
|
|
Expected: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 12,
|
|
},
|
|
},
|
|
"explicit primary, explicit index": {
|
|
Input: "aws_instance.foo.primary[2]",
|
|
Expected: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 2,
|
|
},
|
|
},
|
|
"tainted": {
|
|
Input: "aws_instance.foo.tainted",
|
|
Expected: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypeTainted,
|
|
Index: -1,
|
|
},
|
|
},
|
|
"deposed": {
|
|
Input: "aws_instance.foo.deposed",
|
|
Expected: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypeDeposed,
|
|
Index: -1,
|
|
},
|
|
},
|
|
"with a hyphen": {
|
|
Input: "aws_instance.foo-bar",
|
|
Expected: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo-bar",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
},
|
|
"in a module": {
|
|
Input: "module.child.aws_instance.foo",
|
|
Expected: &ResourceAddress{
|
|
Path: []string{"child"},
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
},
|
|
"nested modules": {
|
|
Input: "module.a.module.b.module.forever.aws_instance.foo",
|
|
Expected: &ResourceAddress{
|
|
Path: []string{"a", "b", "forever"},
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
},
|
|
"just a module": {
|
|
Input: "module.a",
|
|
Expected: &ResourceAddress{
|
|
Path: []string{"a"},
|
|
Type: "",
|
|
Name: "",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
},
|
|
"just a nested module": {
|
|
Input: "module.a.module.b",
|
|
Expected: &ResourceAddress{
|
|
Path: []string{"a", "b"},
|
|
Type: "",
|
|
Name: "",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
},
|
|
}
|
|
|
|
for tn, tc := range cases {
|
|
out, err := ParseResourceAddress(tc.Input)
|
|
if err != nil {
|
|
t.Fatalf("unexpected err: %#v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(out, tc.Expected) {
|
|
t.Fatalf("bad: %q\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Expected, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestResourceAddressEquals(t *testing.T) {
|
|
cases := map[string]struct {
|
|
Address *ResourceAddress
|
|
Other interface{}
|
|
Expect bool
|
|
}{
|
|
"basic match": {
|
|
Address: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Expect: true,
|
|
},
|
|
"address does not set index": {
|
|
Address: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 3,
|
|
},
|
|
Expect: true,
|
|
},
|
|
"other does not set index": {
|
|
Address: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 3,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
Expect: true,
|
|
},
|
|
"neither sets index": {
|
|
Address: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
Expect: true,
|
|
},
|
|
"index over ten": {
|
|
Address: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 1,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 13,
|
|
},
|
|
Expect: false,
|
|
},
|
|
"different type": {
|
|
Address: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Type: "aws_vpc",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Expect: false,
|
|
},
|
|
"different name": {
|
|
Address: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "bar",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Expect: false,
|
|
},
|
|
"different instance type": {
|
|
Address: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypeTainted,
|
|
Index: 0,
|
|
},
|
|
Expect: false,
|
|
},
|
|
"different index": {
|
|
Address: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 1,
|
|
},
|
|
Expect: false,
|
|
},
|
|
"module address matches address of resource inside module": {
|
|
Address: &ResourceAddress{
|
|
Path: []string{"a", "b"},
|
|
Type: "",
|
|
Name: "",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Path: []string{"a", "b"},
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Expect: true,
|
|
},
|
|
"module address doesn't match resource outside module": {
|
|
Address: &ResourceAddress{
|
|
Path: []string{"a", "b"},
|
|
Type: "",
|
|
Name: "",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Path: []string{"a"},
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Expect: false,
|
|
},
|
|
"nil path vs empty path should match": {
|
|
Address: &ResourceAddress{
|
|
Path: []string{},
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: -1,
|
|
},
|
|
Other: &ResourceAddress{
|
|
Path: nil,
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
InstanceType: TypePrimary,
|
|
Index: 0,
|
|
},
|
|
Expect: true,
|
|
},
|
|
}
|
|
|
|
for tn, tc := range cases {
|
|
actual := tc.Address.Equals(tc.Other)
|
|
if actual != tc.Expect {
|
|
t.Fatalf("%q: expected equals: %t, got %t for:\n%#v\n%#v",
|
|
tn, tc.Expect, actual, tc.Address, tc.Other)
|
|
}
|
|
}
|
|
}
|