753 lines
16 KiB
Go
753 lines
16 KiB
Go
|
package addrs
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/google/go-cmp/cmp"
|
||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||
|
"github.com/hashicorp/hcl/v2"
|
||
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||
|
)
|
||
|
|
||
|
func TestParseMoveEndpoint(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
Input string
|
||
|
WantRel AbsMoveable // funny intermediate subset of AbsMovable
|
||
|
WantErr string
|
||
|
}{
|
||
|
{
|
||
|
`foo.bar`,
|
||
|
AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: NoKey,
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`foo.bar[0]`,
|
||
|
AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: IntKey(0),
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`foo.bar["a"]`,
|
||
|
AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: StringKey("a"),
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.boop.foo.bar`,
|
||
|
AbsResourceInstance{
|
||
|
Module: ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "boop"},
|
||
|
},
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: NoKey,
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.boop.foo.bar[0]`,
|
||
|
AbsResourceInstance{
|
||
|
Module: ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "boop"},
|
||
|
},
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: IntKey(0),
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.boop.foo.bar["a"]`,
|
||
|
AbsResourceInstance{
|
||
|
Module: ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "boop"},
|
||
|
},
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: StringKey("a"),
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`data.foo.bar`,
|
||
|
AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: DataResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: NoKey,
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`data.foo.bar[0]`,
|
||
|
AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: DataResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: IntKey(0),
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`data.foo.bar["a"]`,
|
||
|
AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: DataResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: StringKey("a"),
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.boop.data.foo.bar`,
|
||
|
AbsResourceInstance{
|
||
|
Module: ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "boop"},
|
||
|
},
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: DataResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: NoKey,
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.boop.data.foo.bar[0]`,
|
||
|
AbsResourceInstance{
|
||
|
Module: ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "boop"},
|
||
|
},
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: DataResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: IntKey(0),
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.boop.data.foo.bar["a"]`,
|
||
|
AbsResourceInstance{
|
||
|
Module: ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "boop"},
|
||
|
},
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: DataResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: StringKey("a"),
|
||
|
},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.foo`,
|
||
|
ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "foo"},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.foo[0]`,
|
||
|
ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "foo", InstanceKey: IntKey(0)},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.foo["a"]`,
|
||
|
ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "foo", InstanceKey: StringKey("a")},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.foo.module.bar`,
|
||
|
ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "foo"},
|
||
|
ModuleInstanceStep{Name: "bar"},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.foo[1].module.bar`,
|
||
|
ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "foo", InstanceKey: IntKey(1)},
|
||
|
ModuleInstanceStep{Name: "bar"},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.foo.module.bar[1]`,
|
||
|
ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "foo"},
|
||
|
ModuleInstanceStep{Name: "bar", InstanceKey: IntKey(1)},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module.foo[0].module.bar[1]`,
|
||
|
ModuleInstance{
|
||
|
ModuleInstanceStep{Name: "foo", InstanceKey: IntKey(0)},
|
||
|
ModuleInstanceStep{Name: "bar", InstanceKey: IntKey(1)},
|
||
|
},
|
||
|
``,
|
||
|
},
|
||
|
{
|
||
|
`module`,
|
||
|
nil,
|
||
|
`Invalid address operator: Prefix "module." must be followed by a module name.`,
|
||
|
},
|
||
|
{
|
||
|
`module[0]`,
|
||
|
nil,
|
||
|
`Invalid address operator: Prefix "module." must be followed by a module name.`,
|
||
|
},
|
||
|
{
|
||
|
`module.foo.data`,
|
||
|
nil,
|
||
|
`Invalid address: Resource specification must include a resource type and name.`,
|
||
|
},
|
||
|
{
|
||
|
`module.foo.data.bar`,
|
||
|
nil,
|
||
|
`Invalid address: Resource specification must include a resource type and name.`,
|
||
|
},
|
||
|
{
|
||
|
`module.foo.data[0]`,
|
||
|
nil,
|
||
|
`Invalid address: Resource specification must include a resource type and name.`,
|
||
|
},
|
||
|
{
|
||
|
`module.foo.data.bar[0]`,
|
||
|
nil,
|
||
|
`Invalid address: A resource name is required.`,
|
||
|
},
|
||
|
{
|
||
|
`module.foo.bar`,
|
||
|
nil,
|
||
|
`Invalid address: Resource specification must include a resource type and name.`,
|
||
|
},
|
||
|
{
|
||
|
`module.foo.bar[0]`,
|
||
|
nil,
|
||
|
`Invalid address: A resource name is required.`,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
t.Run(test.Input, func(t *testing.T) {
|
||
|
traversal, hclDiags := hclsyntax.ParseTraversalAbs([]byte(test.Input), "", hcl.InitialPos)
|
||
|
if hclDiags.HasErrors() {
|
||
|
// We're not trying to test the HCL parser here, so any
|
||
|
// failures at this point are likely to be bugs in the
|
||
|
// test case itself.
|
||
|
t.Fatalf("syntax error: %s", hclDiags.Error())
|
||
|
}
|
||
|
|
||
|
moveEp, diags := ParseMoveEndpoint(traversal)
|
||
|
|
||
|
switch {
|
||
|
case test.WantErr != "":
|
||
|
if !diags.HasErrors() {
|
||
|
t.Fatalf("unexpected success\nwant error: %s", test.WantErr)
|
||
|
}
|
||
|
gotErr := diags.Err().Error()
|
||
|
if gotErr != test.WantErr {
|
||
|
t.Fatalf("wrong error\ngot: %s\nwant: %s", gotErr, test.WantErr)
|
||
|
}
|
||
|
default:
|
||
|
if diags.HasErrors() {
|
||
|
t.Fatalf("unexpected error: %s", diags.Err().Error())
|
||
|
}
|
||
|
if diff := cmp.Diff(test.WantRel, moveEp.relSubject); diff != "" {
|
||
|
t.Errorf("wrong result\n%s", diff)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestUnifyMoveEndpoints(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
InputFrom, InputTo string
|
||
|
Module ModuleInstance
|
||
|
WantFrom, WantTo AbsMoveable
|
||
|
}{
|
||
|
{
|
||
|
InputFrom: `foo.bar`,
|
||
|
InputTo: `foo.baz`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: AbsResource{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
},
|
||
|
WantTo: AbsResource{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "baz",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `foo.bar`,
|
||
|
InputTo: `foo.baz`,
|
||
|
Module: RootModuleInstance.Child("a", NoKey),
|
||
|
WantFrom: AbsResource{
|
||
|
Module: RootModuleInstance.Child("a", NoKey),
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
},
|
||
|
WantTo: AbsResource{
|
||
|
Module: RootModuleInstance.Child("a", NoKey),
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "baz",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `foo.bar`,
|
||
|
InputTo: `module.b[0].foo.baz`,
|
||
|
Module: RootModuleInstance.Child("a", NoKey),
|
||
|
WantFrom: AbsResource{
|
||
|
Module: RootModuleInstance.Child("a", NoKey),
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
},
|
||
|
WantTo: AbsResource{
|
||
|
Module: RootModuleInstance.Child("a", NoKey).Child("b", IntKey(0)),
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "baz",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `foo.bar`,
|
||
|
InputTo: `foo.bar["thing"]`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
WantTo: AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: StringKey("thing"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `foo.bar["thing"]`,
|
||
|
InputTo: `foo.bar`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: StringKey("thing"),
|
||
|
},
|
||
|
},
|
||
|
WantTo: AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `foo.bar["a"]`,
|
||
|
InputTo: `foo.bar["b"]`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: StringKey("a"),
|
||
|
},
|
||
|
},
|
||
|
WantTo: AbsResourceInstance{
|
||
|
Module: RootModuleInstance,
|
||
|
Resource: ResourceInstance{
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
Key: StringKey("b"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo`,
|
||
|
InputTo: `module.bar`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: AbsModuleCall{
|
||
|
Module: RootModuleInstance,
|
||
|
Call: ModuleCall{Name: "foo"},
|
||
|
},
|
||
|
WantTo: AbsModuleCall{
|
||
|
Module: RootModuleInstance,
|
||
|
Call: ModuleCall{Name: "bar"},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo`,
|
||
|
InputTo: `module.bar.module.baz`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: AbsModuleCall{
|
||
|
Module: RootModuleInstance,
|
||
|
Call: ModuleCall{Name: "foo"},
|
||
|
},
|
||
|
WantTo: AbsModuleCall{
|
||
|
Module: RootModuleInstance.Child("bar", NoKey),
|
||
|
Call: ModuleCall{Name: "baz"},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo`,
|
||
|
InputTo: `module.bar.module.baz`,
|
||
|
Module: RootModuleInstance.Child("bloop", StringKey("hi")),
|
||
|
WantFrom: AbsModuleCall{
|
||
|
Module: RootModuleInstance.Child("bloop", StringKey("hi")),
|
||
|
Call: ModuleCall{Name: "foo"},
|
||
|
},
|
||
|
WantTo: AbsModuleCall{
|
||
|
Module: RootModuleInstance.Child("bloop", StringKey("hi")).Child("bar", NoKey),
|
||
|
Call: ModuleCall{Name: "baz"},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo[0]`,
|
||
|
InputTo: `module.foo["a"]`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: RootModuleInstance.Child("foo", IntKey(0)),
|
||
|
WantTo: RootModuleInstance.Child("foo", StringKey("a")),
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo`,
|
||
|
InputTo: `module.foo["a"]`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: RootModuleInstance.Child("foo", NoKey),
|
||
|
WantTo: RootModuleInstance.Child("foo", StringKey("a")),
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo[0]`,
|
||
|
InputTo: `module.foo`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: RootModuleInstance.Child("foo", IntKey(0)),
|
||
|
WantTo: RootModuleInstance.Child("foo", NoKey),
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo[0]`,
|
||
|
InputTo: `module.foo`,
|
||
|
Module: RootModuleInstance.Child("bloop", NoKey),
|
||
|
WantFrom: RootModuleInstance.Child("bloop", NoKey).Child("foo", IntKey(0)),
|
||
|
WantTo: RootModuleInstance.Child("bloop", NoKey).Child("foo", NoKey),
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo`,
|
||
|
InputTo: `foo.bar`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: nil, // Can't unify module call with resource
|
||
|
WantTo: nil,
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo[0]`,
|
||
|
InputTo: `foo.bar`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: nil, // Can't unify module instance with resource
|
||
|
WantTo: nil,
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo`,
|
||
|
InputTo: `foo.bar[0]`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: nil, // Can't unify module call with resource instance
|
||
|
WantTo: nil,
|
||
|
},
|
||
|
{
|
||
|
InputFrom: `module.foo[0]`,
|
||
|
InputTo: `foo.bar[0]`,
|
||
|
Module: RootModuleInstance,
|
||
|
WantFrom: nil, // Can't unify module instance with resource instance
|
||
|
WantTo: nil,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
t.Run(fmt.Sprintf("%s to %s in %s", test.InputFrom, test.InputTo, test.Module), func(t *testing.T) {
|
||
|
parseInput := func(input string) *MoveEndpoint {
|
||
|
t.Helper()
|
||
|
|
||
|
traversal, hclDiags := hclsyntax.ParseTraversalAbs([]byte(input), "", hcl.InitialPos)
|
||
|
if hclDiags.HasErrors() {
|
||
|
// We're not trying to test the HCL parser here, so any
|
||
|
// failures at this point are likely to be bugs in the
|
||
|
// test case itself.
|
||
|
t.Fatalf("syntax error: %s", hclDiags.Error())
|
||
|
}
|
||
|
|
||
|
moveEp, diags := ParseMoveEndpoint(traversal)
|
||
|
if diags.HasErrors() {
|
||
|
t.Fatalf("unexpected error: %s", diags.Err().Error())
|
||
|
}
|
||
|
return moveEp
|
||
|
}
|
||
|
|
||
|
fromEp := parseInput(test.InputFrom)
|
||
|
toEp := parseInput(test.InputTo)
|
||
|
|
||
|
diffOpts := cmpopts.IgnoreUnexported(ModuleCall{})
|
||
|
gotFrom, gotTo := UnifyMoveEndpoints(test.Module, fromEp, toEp)
|
||
|
if diff := cmp.Diff(test.WantFrom, gotFrom, diffOpts); diff != "" {
|
||
|
t.Errorf("wrong 'from' address\n%s", diff)
|
||
|
}
|
||
|
if diff := cmp.Diff(test.WantTo, gotTo, diffOpts); diff != "" {
|
||
|
t.Errorf("wrong 'to' address\n%s", diff)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestMoveEndpointConfigMoveable(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
Input string
|
||
|
Module Module
|
||
|
Want ConfigMoveable
|
||
|
}{
|
||
|
{
|
||
|
`foo.bar`,
|
||
|
RootModule,
|
||
|
ConfigResource{
|
||
|
Module: RootModule,
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
`foo.bar[0]`,
|
||
|
RootModule,
|
||
|
ConfigResource{
|
||
|
Module: RootModule,
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
`module.foo.bar.baz`,
|
||
|
RootModule,
|
||
|
ConfigResource{
|
||
|
Module: Module{"foo"},
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "bar",
|
||
|
Name: "baz",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
`module.foo[0].bar.baz`,
|
||
|
RootModule,
|
||
|
ConfigResource{
|
||
|
Module: Module{"foo"},
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "bar",
|
||
|
Name: "baz",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
`foo.bar`,
|
||
|
Module{"boop"},
|
||
|
ConfigResource{
|
||
|
Module: Module{"boop"},
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
`module.bloop.foo.bar`,
|
||
|
Module{"bleep"},
|
||
|
ConfigResource{
|
||
|
Module: Module{"bleep", "bloop"},
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "foo",
|
||
|
Name: "bar",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
`module.foo.bar.baz`,
|
||
|
RootModule,
|
||
|
ConfigResource{
|
||
|
Module: Module{"foo"},
|
||
|
Resource: Resource{
|
||
|
Mode: ManagedResourceMode,
|
||
|
Type: "bar",
|
||
|
Name: "baz",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
`module.foo`,
|
||
|
RootModule,
|
||
|
Module{"foo"},
|
||
|
},
|
||
|
{
|
||
|
`module.foo[0]`,
|
||
|
RootModule,
|
||
|
Module{"foo"},
|
||
|
},
|
||
|
{
|
||
|
`module.bloop`,
|
||
|
Module{"bleep"},
|
||
|
Module{"bleep", "bloop"},
|
||
|
},
|
||
|
{
|
||
|
`module.bloop[0]`,
|
||
|
Module{"bleep"},
|
||
|
Module{"bleep", "bloop"},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
t.Run(fmt.Sprintf("%s in %s", test.Input, test.Module), func(t *testing.T) {
|
||
|
traversal, hclDiags := hclsyntax.ParseTraversalAbs([]byte(test.Input), "", hcl.InitialPos)
|
||
|
if hclDiags.HasErrors() {
|
||
|
// We're not trying to test the HCL parser here, so any
|
||
|
// failures at this point are likely to be bugs in the
|
||
|
// test case itself.
|
||
|
t.Fatalf("syntax error: %s", hclDiags.Error())
|
||
|
}
|
||
|
|
||
|
moveEp, diags := ParseMoveEndpoint(traversal)
|
||
|
if diags.HasErrors() {
|
||
|
t.Fatalf("unexpected error: %s", diags.Err().Error())
|
||
|
}
|
||
|
|
||
|
got := moveEp.ConfigMoveable(test.Module)
|
||
|
if diff := cmp.Diff(test.Want, got); diff != "" {
|
||
|
t.Errorf("wrong result\n%s", diff)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|