mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
switch to different types for different parts of the label query
This commit is contained in:
parent
3b980bd9dc
commit
c4e575d4ac
@ -29,7 +29,7 @@ type Labels interface {
|
|||||||
// A map of label:value. Implements Labels.
|
// A map of label:value. Implements Labels.
|
||||||
type Set map[string]string
|
type Set map[string]string
|
||||||
|
|
||||||
// All labels listed as a human readable string. Conveiently, exactly the format
|
// All labels listed as a human readable string. Conveniently, exactly the format
|
||||||
// that ParseQuery takes.
|
// that ParseQuery takes.
|
||||||
func (ls Set) String() string {
|
func (ls Set) String() string {
|
||||||
query := make([]string, 0, len(ls))
|
query := make([]string, 0, len(ls))
|
||||||
|
@ -32,53 +32,50 @@ type Query interface {
|
|||||||
|
|
||||||
// Everything returns a query that matches all labels.
|
// Everything returns a query that matches all labels.
|
||||||
func Everything() Query {
|
func Everything() Query {
|
||||||
return &queryTerm{}
|
return andTerm{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A single term of a label query.
|
type hasTerm struct {
|
||||||
type queryTerm struct {
|
label, value string
|
||||||
// Not inverts the meaning of the items in this term.
|
|
||||||
not bool
|
|
||||||
|
|
||||||
// Exactly one of the below three items should be used.
|
|
||||||
|
|
||||||
// If non-nil, we match Set l iff l[*label] == *value.
|
|
||||||
label, value *string
|
|
||||||
|
|
||||||
// A list of terms which must all match for this query term to return true.
|
|
||||||
and []queryTerm
|
|
||||||
|
|
||||||
// A list of terms, any one of which will cause this query term to return true.
|
|
||||||
// Parsing/printing not implemented.
|
|
||||||
or []queryTerm
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *queryTerm) Matches(ls Labels) bool {
|
func (t *hasTerm) Matches(ls Labels) bool {
|
||||||
matches := !l.not
|
return ls.Get(t.label) == t.value
|
||||||
switch {
|
}
|
||||||
case l.label != nil && l.value != nil:
|
|
||||||
if ls.Get(*l.label) == *l.value {
|
func (t *hasTerm) String() string {
|
||||||
return matches
|
return fmt.Sprintf("%v=%v", t.label, t.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
type notHasTerm struct {
|
||||||
|
label, value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *notHasTerm) Matches(ls Labels) bool {
|
||||||
|
return ls.Get(t.label) != t.value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *notHasTerm) String() string {
|
||||||
|
return fmt.Sprintf("%v!=%v", t.label, t.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
type andTerm []Query
|
||||||
|
|
||||||
|
func (t andTerm) Matches(ls Labels) bool {
|
||||||
|
for _, q := range t {
|
||||||
|
if !q.Matches(ls) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return !matches
|
|
||||||
case len(l.and) > 0:
|
|
||||||
for i := range l.and {
|
|
||||||
if !l.and[i].Matches(ls) {
|
|
||||||
return !matches
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matches
|
|
||||||
case len(l.or) > 0:
|
|
||||||
for i := range l.or {
|
|
||||||
if l.or[i].Matches(ls) {
|
|
||||||
return matches
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return !matches
|
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Empty queries match everything
|
func (t andTerm) String() string {
|
||||||
return matches
|
var terms []string
|
||||||
|
for _, q := range t {
|
||||||
|
terms = append(terms, q.String())
|
||||||
|
}
|
||||||
|
return strings.Join(terms, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
func try(queryPiece, op string) (lhs, rhs string, ok bool) {
|
func try(queryPiece, op string) (lhs, rhs string, ok bool) {
|
||||||
@ -91,55 +88,36 @@ func try(queryPiece, op string) (lhs, rhs string, ok bool) {
|
|||||||
|
|
||||||
// Given a Set, return a Query which will match exactly that Set.
|
// Given a Set, return a Query which will match exactly that Set.
|
||||||
func QueryFromSet(ls Set) Query {
|
func QueryFromSet(ls Set) Query {
|
||||||
var query queryTerm
|
var items []Query
|
||||||
for l, v := range ls {
|
for label, value := range ls {
|
||||||
// Make a copy, because we're taking the address below
|
items = append(items, &hasTerm{label: label, value: value})
|
||||||
label, value := l, v
|
|
||||||
query.and = append(query.and, queryTerm{label: &label, value: &value})
|
|
||||||
}
|
}
|
||||||
return &query
|
if len(items) == 1 {
|
||||||
|
return items[0]
|
||||||
|
}
|
||||||
|
return andTerm(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a string repsenting a label query and returns an object suitable for matching, or an error.
|
// Takes a string repsenting a label query and returns an object suitable for matching, or an error.
|
||||||
func ParseQuery(query string) (Query, error) {
|
func ParseQuery(query string) (Query, error) {
|
||||||
parts := strings.Split(query, ",")
|
parts := strings.Split(query, ",")
|
||||||
var items []queryTerm
|
var items []Query
|
||||||
for _, part := range parts {
|
for _, part := range parts {
|
||||||
if part == "" {
|
if part == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if lhs, rhs, ok := try(part, "!="); ok {
|
if lhs, rhs, ok := try(part, "!="); ok {
|
||||||
items = append(items, queryTerm{not: true, label: &lhs, value: &rhs})
|
items = append(items, ¬HasTerm{label: lhs, value: rhs})
|
||||||
} else if lhs, rhs, ok := try(part, "=="); ok {
|
} else if lhs, rhs, ok := try(part, "=="); ok {
|
||||||
items = append(items, queryTerm{label: &lhs, value: &rhs})
|
items = append(items, &hasTerm{label: lhs, value: rhs})
|
||||||
} else if lhs, rhs, ok := try(part, "="); ok {
|
} else if lhs, rhs, ok := try(part, "="); ok {
|
||||||
items = append(items, queryTerm{label: &lhs, value: &rhs})
|
items = append(items, &hasTerm{label: lhs, value: rhs})
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("invalid label query: '%s'; can't understand '%s'", query, part)
|
return nil, fmt.Errorf("invalid label query: '%s'; can't understand '%s'", query, part)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(items) == 1 {
|
if len(items) == 1 {
|
||||||
return &items[0], nil
|
return items[0], nil
|
||||||
}
|
}
|
||||||
return &queryTerm{and: items}, nil
|
return andTerm(items), nil
|
||||||
}
|
|
||||||
|
|
||||||
// Returns this query as a string in a form that ParseQuery can parse.
|
|
||||||
func (l *queryTerm) String() (out string) {
|
|
||||||
if len(l.and) > 0 {
|
|
||||||
for _, part := range l.and {
|
|
||||||
if out != "" {
|
|
||||||
out += ","
|
|
||||||
}
|
|
||||||
out += part.String()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else if l.label != nil && l.value != nil {
|
|
||||||
op := "="
|
|
||||||
if l.not {
|
|
||||||
op = "!="
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%v%v%v", *l.label, op, *l.value)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user