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
|
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
|
// moduleInstanceCanMatch indicates that modA can match modB taking into
|
||||||
// account steps with an anyKey InstanceKey as wildcards. The comparison of
|
// account steps with an anyKey InstanceKey as wildcards. The comparison of
|
||||||
// wildcard steps is done symmetrically, because varying portions of either
|
// 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 {
|
func mustParseAbsResourceInstanceStr(s string) AbsResourceInstance {
|
||||||
r, diags := ParseAbsResourceInstanceStr(s)
|
r, diags := ParseAbsResourceInstanceStr(s)
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
|
|
Loading…
Reference in New Issue