terraform: parse internal resource addresses used in state/diff
This commit is contained in:
parent
50afee2a30
commit
361bc5a8df
|
@ -85,6 +85,37 @@ func (r *ResourceAddress) String() string {
|
||||||
return strings.Join(result, ".")
|
return strings.Join(result, ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseResourceAddressInternal parses the somewhat bespoke resource
|
||||||
|
// identifier used in states and diffs, such as "instance.name.0".
|
||||||
|
func parseResourceAddressInternal(s string) (*ResourceAddress, error) {
|
||||||
|
// Split based on ".". Every resource address should have at least two
|
||||||
|
// elements (type and name).
|
||||||
|
parts := strings.Split(s, ".")
|
||||||
|
if len(parts) < 2 || len(parts) > 3 {
|
||||||
|
return nil, fmt.Errorf("Invalid internal resource address format: %s", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the parts of the resource address that are guaranteed to exist
|
||||||
|
addr := &ResourceAddress{
|
||||||
|
Type: parts[0],
|
||||||
|
Name: parts[1],
|
||||||
|
Index: -1,
|
||||||
|
InstanceType: TypePrimary,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have more parts, then we have an index. Parse that.
|
||||||
|
if len(parts) > 2 {
|
||||||
|
idx, err := strconv.ParseInt(parts[2], 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Error parsing resource address %q: %s", s, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.Index = int(idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ParseResourceAddress(s string) (*ResourceAddress, error) {
|
func ParseResourceAddress(s string) (*ResourceAddress, error) {
|
||||||
matches, err := tokenizeResourceAddress(s)
|
matches, err := tokenizeResourceAddress(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -7,6 +7,66 @@ import (
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestParseResourceAddressInternal(t *testing.T) {
|
||||||
|
cases := map[string]struct {
|
||||||
|
Input string
|
||||||
|
Expected *ResourceAddress
|
||||||
|
Output string
|
||||||
|
}{
|
||||||
|
"basic resource": {
|
||||||
|
"aws_instance.foo",
|
||||||
|
&ResourceAddress{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "aws_instance",
|
||||||
|
Name: "foo",
|
||||||
|
InstanceType: TypePrimary,
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
"aws_instance.foo",
|
||||||
|
},
|
||||||
|
|
||||||
|
"basic resource with count": {
|
||||||
|
"aws_instance.foo.1",
|
||||||
|
&ResourceAddress{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "aws_instance",
|
||||||
|
Name: "foo",
|
||||||
|
InstanceType: TypePrimary,
|
||||||
|
Index: 1,
|
||||||
|
},
|
||||||
|
"aws_instance.foo[1]",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for tn, tc := range cases {
|
||||||
|
t.Run(tc.Input, func(t *testing.T) {
|
||||||
|
out, err := parseResourceAddressInternal(tc.Input)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%s: unexpected err: %#v", tn, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(out, tc.Expected) {
|
||||||
|
t.Fatalf("bad: %q\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Expected, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare outputs if those exist
|
||||||
|
expected := tc.Input
|
||||||
|
if tc.Output != "" {
|
||||||
|
expected = tc.Output
|
||||||
|
}
|
||||||
|
if out.String() != expected {
|
||||||
|
t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, expected, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare equality because the internal parse is used
|
||||||
|
// to compare equality to equal inputs.
|
||||||
|
if !out.Equals(tc.Expected) {
|
||||||
|
t.Fatalf("expected equality:\n\n%#v\n\n%#v", out, tc.Expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseResourceAddress(t *testing.T) {
|
func TestParseResourceAddress(t *testing.T) {
|
||||||
cases := map[string]struct {
|
cases := map[string]struct {
|
||||||
Input string
|
Input string
|
||||||
|
|
Loading…
Reference in New Issue