addrs: MoveEndpointInModule.SelectsResource
This is similar to the existing SelectsModule method, returning true if the reciever selects either a particular resource as a whole or any of the instances of that resource. We don't need this test in the normal case, but we will need it in a subsequent commit when we'll be possibly generating _implied_ move statements between instances of resources, but only if there aren't explicit move statements mentioning those resources already.
This commit is contained in:
parent
2b6a1be18f
commit
7f99a8802e
|
@ -233,6 +233,37 @@ func (e *MoveEndpointInModule) SelectsModule(addr ModuleInstance) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// SelectsResource returns true if the receiver directly selects either
|
||||
// the given resource or one of its instances.
|
||||
func (e *MoveEndpointInModule) SelectsResource(addr AbsResource) bool {
|
||||
// Only a subset of subject types can possibly select a resource, so
|
||||
// we'll take care of those quickly before we do anything more expensive.
|
||||
switch e.relSubject.(type) {
|
||||
case AbsResource, AbsResourceInstance:
|
||||
// okay
|
||||
default:
|
||||
return false // can't possibly match
|
||||
}
|
||||
|
||||
if !e.SelectsModule(addr.Module) {
|
||||
return false
|
||||
}
|
||||
|
||||
// If we get here then we know the module part matches, so we only need
|
||||
// to worry about the relative resource part.
|
||||
switch relSubject := e.relSubject.(type) {
|
||||
case AbsResource:
|
||||
return addr.Resource.Equal(relSubject.Resource)
|
||||
case AbsResourceInstance:
|
||||
// We intentionally ignore the instance key, because we consider
|
||||
// instances to be part of the resource they belong to.
|
||||
return addr.Resource.Equal(relSubject.Resource.Resource)
|
||||
default:
|
||||
// We should've filtered out all other types above
|
||||
panic(fmt.Sprintf("unsupported relSubject type %T", relSubject))
|
||||
}
|
||||
}
|
||||
|
||||
// moduleInstanceCanMatch indicates that modA can match modB taking into
|
||||
// account steps with an anyKey InstanceKey as wildcards. The comparison of
|
||||
// wildcard steps is done symmetrically, because varying portions of either
|
||||
|
|
|
@ -1457,6 +1457,133 @@ func TestSelectsModule(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSelectsResource(t *testing.T) {
|
||||
matchingResource := Resource{
|
||||
Mode: ManagedResourceMode,
|
||||
Type: "foo",
|
||||
Name: "matching",
|
||||
}
|
||||
unmatchingResource := Resource{
|
||||
Mode: ManagedResourceMode,
|
||||
Type: "foo",
|
||||
Name: "unmatching",
|
||||
}
|
||||
childMod := Module{
|
||||
"child",
|
||||
}
|
||||
childModMatchingInst := ModuleInstance{
|
||||
ModuleInstanceStep{Name: "child", InstanceKey: StringKey("matching")},
|
||||
}
|
||||
childModUnmatchingInst := ModuleInstance{
|
||||
ModuleInstanceStep{Name: "child", InstanceKey: StringKey("unmatching")},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
Endpoint *MoveEndpointInModule
|
||||
Addr AbsResource
|
||||
Selects bool
|
||||
}{
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: matchingResource.Absolute(nil),
|
||||
},
|
||||
Addr: matchingResource.Absolute(nil),
|
||||
Selects: true, // exact match
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: unmatchingResource.Absolute(nil),
|
||||
},
|
||||
Addr: matchingResource.Absolute(nil),
|
||||
Selects: false, // wrong resource name
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: unmatchingResource.Instance(IntKey(1)).Absolute(nil),
|
||||
},
|
||||
Addr: matchingResource.Absolute(nil),
|
||||
Selects: false, // wrong resource name
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: matchingResource.Instance(NoKey).Absolute(nil),
|
||||
},
|
||||
Addr: matchingResource.Absolute(nil),
|
||||
Selects: true, // matches one instance
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: matchingResource.Instance(IntKey(0)).Absolute(nil),
|
||||
},
|
||||
Addr: matchingResource.Absolute(nil),
|
||||
Selects: true, // matches one instance
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: matchingResource.Instance(StringKey("a")).Absolute(nil),
|
||||
},
|
||||
Addr: matchingResource.Absolute(nil),
|
||||
Selects: true, // matches one instance
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
module: childMod,
|
||||
relSubject: matchingResource.Absolute(nil),
|
||||
},
|
||||
Addr: matchingResource.Absolute(childModMatchingInst),
|
||||
Selects: true, // in one of the instances of the module where the statement was written
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: matchingResource.Absolute(childModMatchingInst),
|
||||
},
|
||||
Addr: matchingResource.Absolute(childModMatchingInst),
|
||||
Selects: true, // exact match
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: matchingResource.Instance(IntKey(2)).Absolute(childModMatchingInst),
|
||||
},
|
||||
Addr: matchingResource.Absolute(childModMatchingInst),
|
||||
Selects: true, // matches one instance
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: matchingResource.Absolute(childModMatchingInst),
|
||||
},
|
||||
Addr: matchingResource.Absolute(childModUnmatchingInst),
|
||||
Selects: false, // the containing module instance doesn't match
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: AbsModuleCall{
|
||||
Module: mustParseModuleInstanceStr("module.foo[2]"),
|
||||
Call: ModuleCall{Name: "bar"},
|
||||
},
|
||||
},
|
||||
Addr: matchingResource.Absolute(mustParseModuleInstanceStr("module.foo[2]")),
|
||||
Selects: false, // a module call can't match a resource
|
||||
},
|
||||
{
|
||||
Endpoint: &MoveEndpointInModule{
|
||||
relSubject: mustParseModuleInstanceStr("module.foo[2]"),
|
||||
},
|
||||
Addr: matchingResource.Absolute(mustParseModuleInstanceStr("module.foo[2]")),
|
||||
Selects: false, // a module instance can't match a resource
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(fmt.Sprintf("[%02d]%s SelectsResource(%s)", i, test.Endpoint, test.Addr),
|
||||
func(t *testing.T) {
|
||||
if got, want := test.Endpoint.SelectsResource(test.Addr), test.Selects; got != want {
|
||||
t.Errorf("wrong result\nReceiver: %s\nArgument: %s\ngot: %t\nwant: %t", test.Endpoint, test.Addr, got, want)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func mustParseAbsResourceInstanceStr(s string) AbsResourceInstance {
|
||||
r, diags := ParseAbsResourceInstanceStr(s)
|
||||
if diags.HasErrors() {
|
||||
|
|
Loading…
Reference in New Issue