mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 21:47:07 +00:00
Allow field/label users to get info from fields
Allows a consumer to get at the information stored in the field selector for querying an underlying data store. Not generic, but offers a simple start.
This commit is contained in:
parent
2606ece6e9
commit
ae698bcff8
@ -32,6 +32,12 @@ type Selector interface {
|
|||||||
// Empty returns true if this selector does not restrict the selection space.
|
// Empty returns true if this selector does not restrict the selection space.
|
||||||
Empty() bool
|
Empty() bool
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
// TODO: expand this to be more general
|
||||||
|
RequiresExactMatch(label string) (value string, found bool)
|
||||||
|
|
||||||
// String returns a human readable string that represents this selector.
|
// String returns a human readable string that represents this selector.
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
@ -53,6 +59,13 @@ func (t *hasTerm) Empty() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *hasTerm) RequiresExactMatch(label string) (value string, found bool) {
|
||||||
|
if t.label == label {
|
||||||
|
return t.value, true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
func (t *hasTerm) String() string {
|
func (t *hasTerm) String() string {
|
||||||
return fmt.Sprintf("%v=%v", t.label, t.value)
|
return fmt.Sprintf("%v=%v", t.label, t.value)
|
||||||
}
|
}
|
||||||
@ -69,6 +82,10 @@ func (t *notHasTerm) Empty() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *notHasTerm) RequiresExactMatch(label string) (value string, found bool) {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
func (t *notHasTerm) String() string {
|
func (t *notHasTerm) String() string {
|
||||||
return fmt.Sprintf("%v!=%v", t.label, t.value)
|
return fmt.Sprintf("%v!=%v", t.label, t.value)
|
||||||
}
|
}
|
||||||
@ -99,6 +116,18 @@ func (t andTerm) Empty() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t andTerm) RequiresExactMatch(label string) (string, bool) {
|
||||||
|
if t == nil || len([]Selector(t)) == 0 {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
for i := range t {
|
||||||
|
if value, found := t[i].RequiresExactMatch(label); found {
|
||||||
|
return value, found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
func (t andTerm) String() string {
|
func (t andTerm) String() string {
|
||||||
var terms []string
|
var terms []string
|
||||||
for _, q := range t {
|
for _, q := range t {
|
||||||
@ -173,7 +202,7 @@ func SelectorFromSet(ls Set) Selector {
|
|||||||
return andTerm(items)
|
return andTerm(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseSelector takes a string repsenting a selector and returns an
|
// ParseSelector takes a string representing a selector and returns an
|
||||||
// object suitable for matching, or an error.
|
// object suitable for matching, or an error.
|
||||||
func ParseSelector(selector string) (Selector, error) {
|
func ParseSelector(selector string) (Selector, error) {
|
||||||
parts := strings.Split(selector, ",")
|
parts := strings.Split(selector, ",")
|
||||||
|
@ -158,6 +158,9 @@ func TestSetIsEmpty(t *testing.T) {
|
|||||||
if (&hasTerm{}).Empty() {
|
if (&hasTerm{}).Empty() {
|
||||||
t.Errorf("hasTerm should not be empty")
|
t.Errorf("hasTerm should not be empty")
|
||||||
}
|
}
|
||||||
|
if (¬HasTerm{}).Empty() {
|
||||||
|
t.Errorf("notHasTerm should not be empty")
|
||||||
|
}
|
||||||
if !(andTerm{andTerm{}}).Empty() {
|
if !(andTerm{andTerm{}}).Empty() {
|
||||||
t.Errorf("Nested andTerm should be empty")
|
t.Errorf("Nested andTerm should be empty")
|
||||||
}
|
}
|
||||||
@ -166,6 +169,36 @@ func TestSetIsEmpty(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRequiresExactMatch(t *testing.T) {
|
||||||
|
testCases := map[string]struct {
|
||||||
|
S Selector
|
||||||
|
Label string
|
||||||
|
Value string
|
||||||
|
Found bool
|
||||||
|
}{
|
||||||
|
"empty set": {Set{}.AsSelector(), "test", "", false},
|
||||||
|
"nil andTerm": {andTerm(nil), "test", "", false},
|
||||||
|
"empty hasTerm": {&hasTerm{}, "test", "", false},
|
||||||
|
"skipped hasTerm": {&hasTerm{"a", "b"}, "test", "", false},
|
||||||
|
"valid hasTerm": {&hasTerm{"test", "b"}, "test", "b", true},
|
||||||
|
"valid hasTerm no value": {&hasTerm{"test", ""}, "test", "", true},
|
||||||
|
"valid notHasTerm": {¬HasTerm{"test", "b"}, "test", "", false},
|
||||||
|
"valid notHasTerm no value": {¬HasTerm{"test", ""}, "test", "", false},
|
||||||
|
"nested andTerm": {andTerm{andTerm{}}, "test", "", false},
|
||||||
|
"nested andTerm matches": {andTerm{&hasTerm{"test", "b"}}, "test", "b", true},
|
||||||
|
"andTerm with non-match": {andTerm{&hasTerm{}, &hasTerm{"test", "b"}}, "test", "b", true},
|
||||||
|
}
|
||||||
|
for k, v := range testCases {
|
||||||
|
value, found := v.S.RequiresExactMatch(v.Label)
|
||||||
|
if value != v.Value {
|
||||||
|
t.Errorf("%s: expected value %s, got %s", k, v.Value, value)
|
||||||
|
}
|
||||||
|
if found != v.Found {
|
||||||
|
t.Errorf("%s: expected found %s, got %s", k, v.Found, found)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func expectMatchRequirement(t *testing.T, req Requirement, ls Set) {
|
func expectMatchRequirement(t *testing.T, req Requirement, ls Set) {
|
||||||
if !req.Matches(ls) {
|
if !req.Matches(ls) {
|
||||||
t.Errorf("Wanted '%+v' to match '%s', but it did not.\n", req, ls)
|
t.Errorf("Wanted '%+v' to match '%s', but it did not.\n", req, ls)
|
||||||
|
Loading…
Reference in New Issue
Block a user