add RequiresExactMatch for label.Selector

Signed-off-by: shaloulcy <lcy041536@gmail.com>
This commit is contained in:
shaloulcy 2019-11-10 09:39:59 +08:00
parent 36acfecd4b
commit 5a23bffd42
2 changed files with 107 additions and 6 deletions

View File

@ -54,6 +54,11 @@ type Selector interface {
// Make a deep copy of the selector.
DeepCopySelector() Selector
// RequiresExactMatch allows a caller to introspect whether a given selector
// requires a single specific label to be set, and if so returns the value it
// requires.
RequiresExactMatch(label string) (value string, found bool)
}
// Everything returns a selector that matches all labels.
@ -63,12 +68,13 @@ func Everything() Selector {
type nothingSelector struct{}
func (n nothingSelector) Matches(_ Labels) bool { return false }
func (n nothingSelector) Empty() bool { return false }
func (n nothingSelector) String() string { return "" }
func (n nothingSelector) Add(_ ...Requirement) Selector { return n }
func (n nothingSelector) Requirements() (Requirements, bool) { return nil, false }
func (n nothingSelector) DeepCopySelector() Selector { return n }
func (n nothingSelector) Matches(_ Labels) bool { return false }
func (n nothingSelector) Empty() bool { return false }
func (n nothingSelector) String() string { return "" }
func (n nothingSelector) Add(_ ...Requirement) Selector { return n }
func (n nothingSelector) Requirements() (Requirements, bool) { return nil, false }
func (n nothingSelector) DeepCopySelector() Selector { return n }
func (n nothingSelector) RequiresExactMatch(label string) (value string, found bool) { return "", false }
// Nothing returns a selector that matches no labels
func Nothing() Selector {
@ -358,6 +364,23 @@ func (lsel internalSelector) String() string {
return strings.Join(reqs, ",")
}
// RequiresExactMatch introspect whether a given selector requires a single specific field
// to be set, and if so returns the value it requires.
func (lsel internalSelector) RequiresExactMatch(label string) (value string, found bool) {
for ix := range lsel {
if lsel[ix].key == label {
switch lsel[ix].operator {
case selection.Equals, selection.DoubleEquals, selection.In:
if len(lsel[ix].strValues) == 1 {
return lsel[ix].strValues[0], true
}
}
return "", false
}
}
return "", false
}
// Token represents constant definition for lexer token
type Token int

View File

@ -630,3 +630,81 @@ func BenchmarkSelectorFromValidatedSet(b *testing.B) {
}
}
}
func TestRequiresExactMatch(t *testing.T) {
testCases := []struct {
name string
sel Selector
label string
expectedFound bool
expectedValue string
}{
{
name: "keyInOperatorExactMatch",
sel: internalSelector{Requirement{"key", selection.In, []string{"value"}}},
label: "key",
expectedFound: true,
expectedValue: "value",
},
{
name: "keyInOperatorNotExactMatch",
sel: internalSelector{Requirement{"key", selection.In, []string{"value", "value2"}}},
label: "key",
expectedFound: false,
expectedValue: "",
},
{
name: "keyInOperatorNotExactMatch",
sel: internalSelector{
Requirement{"key", selection.In, []string{"value", "value1"}},
Requirement{"key2", selection.In, []string{"value2"}},
},
label: "key2",
expectedFound: true,
expectedValue: "value2",
},
{
name: "keyEqualOperatorExactMatch",
sel: internalSelector{Requirement{"key", selection.Equals, []string{"value"}}},
label: "key",
expectedFound: true,
expectedValue: "value",
},
{
name: "keyDoubleEqualOperatorExactMatch",
sel: internalSelector{Requirement{"key", selection.DoubleEquals, []string{"value"}}},
label: "key",
expectedFound: true,
expectedValue: "value",
},
{
name: "keyNotEqualOperatorExactMatch",
sel: internalSelector{Requirement{"key", selection.NotEquals, []string{"value"}}},
label: "key",
expectedFound: false,
expectedValue: "",
},
{
name: "keyEqualOperatorExactMatchFirst",
sel: internalSelector{
Requirement{"key", selection.In, []string{"value"}},
Requirement{"key2", selection.In, []string{"value2"}},
},
label: "key",
expectedFound: true,
expectedValue: "value",
},
}
for _, ts := range testCases {
t.Run(ts.name, func(t *testing.T) {
value, found := ts.sel.RequiresExactMatch(ts.label)
if found != ts.expectedFound {
t.Errorf("Expected match %v, found %v", ts.expectedFound, found)
}
if found && value != ts.expectedValue {
t.Errorf("Expected value %v, found %v", ts.expectedValue, value)
}
})
}
}