mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 11:21:47 +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.
|
||||
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.
|
||||
func (ls Set) String() string {
|
||||
query := make([]string, 0, len(ls))
|
||||
|
@ -32,53 +32,50 @@ type Query interface {
|
||||
|
||||
// Everything returns a query that matches all labels.
|
||||
func Everything() Query {
|
||||
return &queryTerm{}
|
||||
return andTerm{}
|
||||
}
|
||||
|
||||
// A single term of a label query.
|
||||
type queryTerm struct {
|
||||
// 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
|
||||
type hasTerm struct {
|
||||
label, value string
|
||||
}
|
||||
|
||||
func (l *queryTerm) Matches(ls Labels) bool {
|
||||
matches := !l.not
|
||||
switch {
|
||||
case l.label != nil && l.value != nil:
|
||||
if ls.Get(*l.label) == *l.value {
|
||||
return matches
|
||||
func (t *hasTerm) Matches(ls Labels) bool {
|
||||
return ls.Get(t.label) == t.value
|
||||
}
|
||||
|
||||
func (t *hasTerm) String() string {
|
||||
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
|
||||
return matches
|
||||
func (t andTerm) String() string {
|
||||
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) {
|
||||
@ -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.
|
||||
func QueryFromSet(ls Set) Query {
|
||||
var query queryTerm
|
||||
for l, v := range ls {
|
||||
// Make a copy, because we're taking the address below
|
||||
label, value := l, v
|
||||
query.and = append(query.and, queryTerm{label: &label, value: &value})
|
||||
var items []Query
|
||||
for label, value := range ls {
|
||||
items = append(items, &hasTerm{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.
|
||||
func ParseQuery(query string) (Query, error) {
|
||||
parts := strings.Split(query, ",")
|
||||
var items []queryTerm
|
||||
var items []Query
|
||||
for _, part := range parts {
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
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 {
|
||||
items = append(items, queryTerm{label: &lhs, value: &rhs})
|
||||
items = append(items, &hasTerm{label: lhs, value: rhs})
|
||||
} 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 {
|
||||
return nil, fmt.Errorf("invalid label query: '%s'; can't understand '%s'", query, part)
|
||||
}
|
||||
}
|
||||
if len(items) == 1 {
|
||||
return &items[0], nil
|
||||
return items[0], nil
|
||||
}
|
||||
return &queryTerm{and: 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 ""
|
||||
return andTerm(items), nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user