core: ResourceAddress.MatchesConfig method
This is a useful building block for filtering configuration based on a resource address. It is similar in principle to state filtering, but for specific resource configuration blocks.
This commit is contained in:
parent
f695e8b330
commit
b82ef2e30e
|
@ -8,6 +8,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
|
"github.com/hashicorp/terraform/config/module"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResourceAddress is a way of identifying an individual resource (or,
|
// ResourceAddress is a way of identifying an individual resource (or,
|
||||||
|
@ -108,6 +109,32 @@ func (r *ResourceAddress) WholeModuleAddress() *ResourceAddress {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchesConfig returns true if the receiver matches the given
|
||||||
|
// configuration resource within the given configuration module.
|
||||||
|
//
|
||||||
|
// Since resource configuration blocks represent all of the instances of
|
||||||
|
// a multi-instance resource, the index of the address (if any) is not
|
||||||
|
// considered.
|
||||||
|
func (r *ResourceAddress) MatchesConfig(mod *module.Tree, rc *config.Resource) bool {
|
||||||
|
if r.HasResourceSpec() {
|
||||||
|
if r.Mode != rc.Mode || r.Type != rc.Type || r.Name != rc.Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addrPath := r.Path
|
||||||
|
cfgPath := mod.Path()
|
||||||
|
|
||||||
|
// normalize
|
||||||
|
if len(addrPath) == 0 {
|
||||||
|
addrPath = nil
|
||||||
|
}
|
||||||
|
if len(cfgPath) == 0 {
|
||||||
|
cfgPath = nil
|
||||||
|
}
|
||||||
|
return reflect.DeepEqual(addrPath, cfgPath)
|
||||||
|
}
|
||||||
|
|
||||||
// stateId returns the ID that this resource should be entered with
|
// stateId returns the ID that this resource should be entered with
|
||||||
// in the state. This is also used for diffs. In the future, we'd like to
|
// in the state. This is also used for diffs. In the future, we'd like to
|
||||||
// move away from this string field so I don't export this.
|
// move away from this string field so I don't export this.
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
|
"github.com/hashicorp/terraform/config/module"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseResourceAddressInternal(t *testing.T) {
|
func TestParseResourceAddressInternal(t *testing.T) {
|
||||||
|
@ -743,3 +745,179 @@ func TestResourceAddressWholeModuleAddress(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResourceAddressMatchesConfig(t *testing.T) {
|
||||||
|
root := testModule(t, "empty-with-child-module")
|
||||||
|
child := root.Child([]string{"child"})
|
||||||
|
grandchild := root.Child([]string{"child", "grandchild"})
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
Addr *ResourceAddress
|
||||||
|
Module *module.Tree
|
||||||
|
Resource *config.Resource
|
||||||
|
Want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
&ResourceAddress{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
root,
|
||||||
|
&config.Resource{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&ResourceAddress{
|
||||||
|
Path: []string{"child"},
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
child,
|
||||||
|
&config.Resource{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&ResourceAddress{
|
||||||
|
Path: []string{"child", "grandchild"},
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
grandchild,
|
||||||
|
&config.Resource{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&ResourceAddress{
|
||||||
|
Path: []string{"child"},
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
child,
|
||||||
|
&config.Resource{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&ResourceAddress{
|
||||||
|
Path: []string{"child", "grandchild"},
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
grandchild,
|
||||||
|
&config.Resource{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&ResourceAddress{
|
||||||
|
Mode: config.DataResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
module.NewEmptyTree(),
|
||||||
|
&config.Resource{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&ResourceAddress{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
module.NewEmptyTree(),
|
||||||
|
&config.Resource{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "pizza",
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&ResourceAddress{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
module.NewEmptyTree(),
|
||||||
|
&config.Resource{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "aws_instance",
|
||||||
|
Name: "baz",
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&ResourceAddress{
|
||||||
|
Path: []string{"child", "grandchild"},
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
child,
|
||||||
|
&config.Resource{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&ResourceAddress{
|
||||||
|
Path: []string{"child"},
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
Index: -1,
|
||||||
|
},
|
||||||
|
grandchild,
|
||||||
|
&config.Resource{
|
||||||
|
Mode: config.ManagedResourceMode,
|
||||||
|
Type: "null_resource",
|
||||||
|
Name: "baz",
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range tests {
|
||||||
|
t.Run(fmt.Sprintf("%02d-%s", i, test.Addr), func(t *testing.T) {
|
||||||
|
got := test.Addr.MatchesConfig(test.Module, test.Resource)
|
||||||
|
if got != test.Want {
|
||||||
|
t.Errorf(
|
||||||
|
"wrong result\naddr: %s\nmod: %#v\nrsrc: %#v\ngot: %#v\nwant: %#v",
|
||||||
|
test.Addr, test.Module.Path(), test.Resource, got, test.Want,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
module "grandchild" {
|
||||||
|
source = "../grandchild"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
# Nothing here!
|
|
@ -0,0 +1,3 @@
|
||||||
|
module "child" {
|
||||||
|
source = "./child"
|
||||||
|
}
|
Loading…
Reference in New Issue