mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-14 13:45:06 +00:00
Merge pull request #30658 from hongchaodeng/r2
Automatic merge from submit-queue Make labels, fields expose selectable requirements What? This is to change the labels/fields Selector interface and make them expose selectable requirements. We reuse labels.Requirement struct for label selector and add fields.Requirement for field selector. Why? In order to index labels/fields, we need them to tell us three things: index key (a field or a label), operator (greater, less, or equal), and value (string, int, etc.). By getting selectable requirements, we are able to pass them down and use them for indexing in storage layer.
This commit is contained in:
@@ -30,6 +30,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/fields"
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
|
"k8s.io/kubernetes/pkg/selection"
|
||||||
"k8s.io/kubernetes/pkg/types"
|
"k8s.io/kubernetes/pkg/types"
|
||||||
"k8s.io/kubernetes/pkg/util/sets"
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
|
|
||||||
@@ -383,20 +384,20 @@ func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.S
|
|||||||
}
|
}
|
||||||
selector := labels.NewSelector()
|
selector := labels.NewSelector()
|
||||||
for _, expr := range nsm {
|
for _, expr := range nsm {
|
||||||
var op labels.Operator
|
var op selection.Operator
|
||||||
switch expr.Operator {
|
switch expr.Operator {
|
||||||
case NodeSelectorOpIn:
|
case NodeSelectorOpIn:
|
||||||
op = labels.InOperator
|
op = selection.In
|
||||||
case NodeSelectorOpNotIn:
|
case NodeSelectorOpNotIn:
|
||||||
op = labels.NotInOperator
|
op = selection.NotIn
|
||||||
case NodeSelectorOpExists:
|
case NodeSelectorOpExists:
|
||||||
op = labels.ExistsOperator
|
op = selection.Exists
|
||||||
case NodeSelectorOpDoesNotExist:
|
case NodeSelectorOpDoesNotExist:
|
||||||
op = labels.DoesNotExistOperator
|
op = selection.DoesNotExist
|
||||||
case NodeSelectorOpGt:
|
case NodeSelectorOpGt:
|
||||||
op = labels.GreaterThanOperator
|
op = selection.GreaterThan
|
||||||
case NodeSelectorOpLt:
|
case NodeSelectorOpLt:
|
||||||
op = labels.LessThanOperator
|
op = selection.LessThan
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
|
return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
|
"k8s.io/kubernetes/pkg/selection"
|
||||||
"k8s.io/kubernetes/pkg/util/sets"
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,23 +36,23 @@ func LabelSelectorAsSelector(ps *LabelSelector) (labels.Selector, error) {
|
|||||||
}
|
}
|
||||||
selector := labels.NewSelector()
|
selector := labels.NewSelector()
|
||||||
for k, v := range ps.MatchLabels {
|
for k, v := range ps.MatchLabels {
|
||||||
r, err := labels.NewRequirement(k, labels.EqualsOperator, sets.NewString(v))
|
r, err := labels.NewRequirement(k, selection.Equals, sets.NewString(v))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
selector = selector.Add(*r)
|
selector = selector.Add(*r)
|
||||||
}
|
}
|
||||||
for _, expr := range ps.MatchExpressions {
|
for _, expr := range ps.MatchExpressions {
|
||||||
var op labels.Operator
|
var op selection.Operator
|
||||||
switch expr.Operator {
|
switch expr.Operator {
|
||||||
case LabelSelectorOpIn:
|
case LabelSelectorOpIn:
|
||||||
op = labels.InOperator
|
op = selection.In
|
||||||
case LabelSelectorOpNotIn:
|
case LabelSelectorOpNotIn:
|
||||||
op = labels.NotInOperator
|
op = selection.NotIn
|
||||||
case LabelSelectorOpExists:
|
case LabelSelectorOpExists:
|
||||||
op = labels.ExistsOperator
|
op = selection.Exists
|
||||||
case LabelSelectorOpDoesNotExist:
|
case LabelSelectorOpDoesNotExist:
|
||||||
op = labels.DoesNotExistOperator
|
op = selection.DoesNotExist
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%q is not a valid pod selector operator", expr.Operator)
|
return nil, fmt.Errorf("%q is not a valid pod selector operator", expr.Operator)
|
||||||
}
|
}
|
||||||
@@ -108,7 +109,7 @@ func ParseToLabelSelector(selector string) (*LabelSelector, error) {
|
|||||||
for _, req := range reqs {
|
for _, req := range reqs {
|
||||||
var op LabelSelectorOperator
|
var op LabelSelectorOperator
|
||||||
switch req.Operator() {
|
switch req.Operator() {
|
||||||
case labels.EqualsOperator, labels.DoubleEqualsOperator:
|
case selection.Equals, selection.DoubleEquals:
|
||||||
vals := req.Values()
|
vals := req.Values()
|
||||||
if vals.Len() != 1 {
|
if vals.Len() != 1 {
|
||||||
return nil, fmt.Errorf("equals operator must have exactly one value")
|
return nil, fmt.Errorf("equals operator must have exactly one value")
|
||||||
@@ -119,15 +120,15 @@ func ParseToLabelSelector(selector string) (*LabelSelector, error) {
|
|||||||
}
|
}
|
||||||
labelSelector.MatchLabels[req.Key()] = val
|
labelSelector.MatchLabels[req.Key()] = val
|
||||||
continue
|
continue
|
||||||
case labels.InOperator:
|
case selection.In:
|
||||||
op = LabelSelectorOpIn
|
op = LabelSelectorOpIn
|
||||||
case labels.NotInOperator:
|
case selection.NotIn:
|
||||||
op = LabelSelectorOpNotIn
|
op = LabelSelectorOpNotIn
|
||||||
case labels.ExistsOperator:
|
case selection.Exists:
|
||||||
op = LabelSelectorOpExists
|
op = LabelSelectorOpExists
|
||||||
case labels.DoesNotExistOperator:
|
case selection.DoesNotExist:
|
||||||
op = LabelSelectorOpDoesNotExist
|
op = LabelSelectorOpDoesNotExist
|
||||||
case labels.GreaterThanOperator, labels.LessThanOperator:
|
case selection.GreaterThan, selection.LessThan:
|
||||||
// Adding a separate case for these operators to indicate that this is deliberate
|
// Adding a separate case for these operators to indicate that this is deliberate
|
||||||
return nil, fmt.Errorf("%q isn't supported in label selectors", req.Operator())
|
return nil, fmt.Errorf("%q isn't supported in label selectors", req.Operator())
|
||||||
default:
|
default:
|
||||||
|
30
pkg/fields/requirements.go
Normal file
30
pkg/fields/requirements.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package fields
|
||||||
|
|
||||||
|
import "k8s.io/kubernetes/pkg/selection"
|
||||||
|
|
||||||
|
// Requirements is AND of all requirements.
|
||||||
|
type Requirements []Requirement
|
||||||
|
|
||||||
|
// Requirement contains a field, a value, and an operator that relates the field and value.
|
||||||
|
// This is currently for reading internal selection information of field selector.
|
||||||
|
type Requirement struct {
|
||||||
|
Operator selection.Operator
|
||||||
|
Field string
|
||||||
|
Value string
|
||||||
|
}
|
@@ -20,6 +20,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/selection"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Selector represents a field selector.
|
// Selector represents a field selector.
|
||||||
@@ -39,6 +41,10 @@ type Selector interface {
|
|||||||
// applied to the entire selector, or an error if fn returns an error.
|
// applied to the entire selector, or an error if fn returns an error.
|
||||||
Transform(fn TransformFunc) (Selector, error)
|
Transform(fn TransformFunc) (Selector, error)
|
||||||
|
|
||||||
|
// Requirements converts this interface to Requirements to expose
|
||||||
|
// more detailed selection information.
|
||||||
|
Requirements() Requirements
|
||||||
|
|
||||||
// String returns a human readable string that represents this selector.
|
// String returns a human readable string that represents this selector.
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
@@ -75,6 +81,14 @@ func (t *hasTerm) Transform(fn TransformFunc) (Selector, error) {
|
|||||||
return &hasTerm{field, value}, nil
|
return &hasTerm{field, value}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *hasTerm) Requirements() Requirements {
|
||||||
|
return []Requirement{{
|
||||||
|
Field: t.field,
|
||||||
|
Operator: selection.Equals,
|
||||||
|
Value: t.value,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *hasTerm) String() string {
|
func (t *hasTerm) String() string {
|
||||||
return fmt.Sprintf("%v=%v", t.field, t.value)
|
return fmt.Sprintf("%v=%v", t.field, t.value)
|
||||||
}
|
}
|
||||||
@@ -103,6 +117,14 @@ func (t *notHasTerm) Transform(fn TransformFunc) (Selector, error) {
|
|||||||
return ¬HasTerm{field, value}, nil
|
return ¬HasTerm{field, value}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *notHasTerm) Requirements() Requirements {
|
||||||
|
return []Requirement{{
|
||||||
|
Field: t.field,
|
||||||
|
Operator: selection.NotEquals,
|
||||||
|
Value: t.value,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *notHasTerm) String() string {
|
func (t *notHasTerm) String() string {
|
||||||
return fmt.Sprintf("%v!=%v", t.field, t.value)
|
return fmt.Sprintf("%v!=%v", t.field, t.value)
|
||||||
}
|
}
|
||||||
@@ -157,6 +179,15 @@ func (t andTerm) Transform(fn TransformFunc) (Selector, error) {
|
|||||||
return andTerm(next), nil
|
return andTerm(next), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t andTerm) Requirements() Requirements {
|
||||||
|
reqs := make([]Requirement, 0, len(t))
|
||||||
|
for _, s := range []Selector(t) {
|
||||||
|
rs := s.Requirements()
|
||||||
|
reqs = append(reqs, rs...)
|
||||||
|
}
|
||||||
|
return reqs
|
||||||
|
}
|
||||||
|
|
||||||
func (t andTerm) String() string {
|
func (t andTerm) String() string {
|
||||||
var terms []string
|
var terms []string
|
||||||
for _, q := range t {
|
for _, q := range t {
|
||||||
|
@@ -24,10 +24,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
"k8s.io/kubernetes/pkg/selection"
|
||||||
"k8s.io/kubernetes/pkg/util/sets"
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
"k8s.io/kubernetes/pkg/util/validation"
|
"k8s.io/kubernetes/pkg/util/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Requirements is AND of all requirements.
|
||||||
|
type Requirements []Requirement
|
||||||
|
|
||||||
// Selector represents a label selector.
|
// Selector represents a label selector.
|
||||||
type Selector interface {
|
type Selector interface {
|
||||||
// Matches returns true if this selector matches the given set of labels.
|
// Matches returns true if this selector matches the given set of labels.
|
||||||
@@ -41,6 +45,12 @@ type Selector interface {
|
|||||||
|
|
||||||
// Add adds requirements to the Selector
|
// Add adds requirements to the Selector
|
||||||
Add(r ...Requirement) Selector
|
Add(r ...Requirement) Selector
|
||||||
|
|
||||||
|
// Requirements converts this interface into Requirements to expose
|
||||||
|
// more detailed selection information.
|
||||||
|
// If there are querying parameters, it will return converted requirements and selectable=true.
|
||||||
|
// If this selector doesn't want to select anything, it will return selectable=false.
|
||||||
|
Requirements() (requirements Requirements, selectable bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything returns a selector that matches all labels.
|
// Everything returns a selector that matches all labels.
|
||||||
@@ -54,28 +64,13 @@ func (n nothingSelector) Matches(_ Labels) bool { return false }
|
|||||||
func (n nothingSelector) Empty() bool { return false }
|
func (n nothingSelector) Empty() bool { return false }
|
||||||
func (n nothingSelector) String() string { return "<null>" }
|
func (n nothingSelector) String() string { return "<null>" }
|
||||||
func (n nothingSelector) Add(_ ...Requirement) Selector { return n }
|
func (n nothingSelector) Add(_ ...Requirement) Selector { return n }
|
||||||
|
func (n nothingSelector) Requirements() (Requirements, bool) { return nil, false }
|
||||||
|
|
||||||
// Nothing returns a selector that matches no labels
|
// Nothing returns a selector that matches no labels
|
||||||
func Nothing() Selector {
|
func Nothing() Selector {
|
||||||
return nothingSelector{}
|
return nothingSelector{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Operator represents a key's relationship
|
|
||||||
// to a set of values in a Requirement.
|
|
||||||
type Operator string
|
|
||||||
|
|
||||||
const (
|
|
||||||
DoesNotExistOperator Operator = "!"
|
|
||||||
EqualsOperator Operator = "="
|
|
||||||
DoubleEqualsOperator Operator = "=="
|
|
||||||
InOperator Operator = "in"
|
|
||||||
NotEqualsOperator Operator = "!="
|
|
||||||
NotInOperator Operator = "notin"
|
|
||||||
ExistsOperator Operator = "exists"
|
|
||||||
GreaterThanOperator Operator = "gt"
|
|
||||||
LessThanOperator Operator = "lt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewSelector() Selector {
|
func NewSelector() Selector {
|
||||||
return internalSelector(nil)
|
return internalSelector(nil)
|
||||||
}
|
}
|
||||||
@@ -91,14 +86,13 @@ func (a ByKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|||||||
|
|
||||||
func (a ByKey) Less(i, j int) bool { return a[i].key < a[j].key }
|
func (a ByKey) Less(i, j int) bool { return a[i].key < a[j].key }
|
||||||
|
|
||||||
// Requirement is a selector that contains values, a key
|
// Requirement contains values, a key, and an operator that relates the key and values.
|
||||||
// and an operator that relates the key and values. The zero
|
// The zero value of Requirement is invalid.
|
||||||
// value of Requirement is invalid.
|
|
||||||
// Requirement implements both set based match and exact match
|
// Requirement implements both set based match and exact match
|
||||||
// Requirement is initialized via NewRequirement constructor for creating a valid Requirement.
|
// Requirement should be initialized via NewRequirement constructor for creating a valid Requirement.
|
||||||
type Requirement struct {
|
type Requirement struct {
|
||||||
key string
|
key string
|
||||||
operator Operator
|
operator selection.Operator
|
||||||
strValues sets.String
|
strValues sets.String
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,24 +107,24 @@ type Requirement struct {
|
|||||||
// of characters. See validateLabelKey for more details.
|
// of characters. See validateLabelKey for more details.
|
||||||
//
|
//
|
||||||
// The empty string is a valid value in the input values set.
|
// The empty string is a valid value in the input values set.
|
||||||
func NewRequirement(key string, op Operator, vals sets.String) (*Requirement, error) {
|
func NewRequirement(key string, op selection.Operator, vals sets.String) (*Requirement, error) {
|
||||||
if err := validateLabelKey(key); err != nil {
|
if err := validateLabelKey(key); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
switch op {
|
switch op {
|
||||||
case InOperator, NotInOperator:
|
case selection.In, selection.NotIn:
|
||||||
if len(vals) == 0 {
|
if len(vals) == 0 {
|
||||||
return nil, fmt.Errorf("for 'in', 'notin' operators, values set can't be empty")
|
return nil, fmt.Errorf("for 'in', 'notin' operators, values set can't be empty")
|
||||||
}
|
}
|
||||||
case EqualsOperator, DoubleEqualsOperator, NotEqualsOperator:
|
case selection.Equals, selection.DoubleEquals, selection.NotEquals:
|
||||||
if len(vals) != 1 {
|
if len(vals) != 1 {
|
||||||
return nil, fmt.Errorf("exact-match compatibility requires one single value")
|
return nil, fmt.Errorf("exact-match compatibility requires one single value")
|
||||||
}
|
}
|
||||||
case ExistsOperator, DoesNotExistOperator:
|
case selection.Exists, selection.DoesNotExist:
|
||||||
if len(vals) != 0 {
|
if len(vals) != 0 {
|
||||||
return nil, fmt.Errorf("values set must be empty for exists and does not exist")
|
return nil, fmt.Errorf("values set must be empty for exists and does not exist")
|
||||||
}
|
}
|
||||||
case GreaterThanOperator, LessThanOperator:
|
case selection.GreaterThan, selection.LessThan:
|
||||||
if len(vals) != 1 {
|
if len(vals) != 1 {
|
||||||
return nil, fmt.Errorf("for 'Gt', 'Lt' operators, exactly one value is required")
|
return nil, fmt.Errorf("for 'Gt', 'Lt' operators, exactly one value is required")
|
||||||
}
|
}
|
||||||
@@ -164,21 +158,21 @@ func NewRequirement(key string, op Operator, vals sets.String) (*Requirement, er
|
|||||||
// the Requirement's key and the corresponding value satisfies mathematical inequality.
|
// the Requirement's key and the corresponding value satisfies mathematical inequality.
|
||||||
func (r *Requirement) Matches(ls Labels) bool {
|
func (r *Requirement) Matches(ls Labels) bool {
|
||||||
switch r.operator {
|
switch r.operator {
|
||||||
case InOperator, EqualsOperator, DoubleEqualsOperator:
|
case selection.In, selection.Equals, selection.DoubleEquals:
|
||||||
if !ls.Has(r.key) {
|
if !ls.Has(r.key) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return r.strValues.Has(ls.Get(r.key))
|
return r.strValues.Has(ls.Get(r.key))
|
||||||
case NotInOperator, NotEqualsOperator:
|
case selection.NotIn, selection.NotEquals:
|
||||||
if !ls.Has(r.key) {
|
if !ls.Has(r.key) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return !r.strValues.Has(ls.Get(r.key))
|
return !r.strValues.Has(ls.Get(r.key))
|
||||||
case ExistsOperator:
|
case selection.Exists:
|
||||||
return ls.Has(r.key)
|
return ls.Has(r.key)
|
||||||
case DoesNotExistOperator:
|
case selection.DoesNotExist:
|
||||||
return !ls.Has(r.key)
|
return !ls.Has(r.key)
|
||||||
case GreaterThanOperator, LessThanOperator:
|
case selection.GreaterThan, selection.LessThan:
|
||||||
if !ls.Has(r.key) {
|
if !ls.Has(r.key) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -202,7 +196,7 @@ func (r *Requirement) Matches(ls Labels) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (r.operator == GreaterThanOperator && lsValue > rValue) || (r.operator == LessThanOperator && lsValue < rValue)
|
return (r.operator == selection.GreaterThan && lsValue > rValue) || (r.operator == selection.LessThan && lsValue < rValue)
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -211,7 +205,7 @@ func (r *Requirement) Matches(ls Labels) bool {
|
|||||||
func (r *Requirement) Key() string {
|
func (r *Requirement) Key() string {
|
||||||
return r.key
|
return r.key
|
||||||
}
|
}
|
||||||
func (r *Requirement) Operator() Operator {
|
func (r *Requirement) Operator() selection.Operator {
|
||||||
return r.operator
|
return r.operator
|
||||||
}
|
}
|
||||||
func (r *Requirement) Values() sets.String {
|
func (r *Requirement) Values() sets.String {
|
||||||
@@ -235,32 +229,32 @@ func (lsel internalSelector) Empty() bool {
|
|||||||
// returned. See NewRequirement for creating a valid Requirement.
|
// returned. See NewRequirement for creating a valid Requirement.
|
||||||
func (r *Requirement) String() string {
|
func (r *Requirement) String() string {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
if r.operator == DoesNotExistOperator {
|
if r.operator == selection.DoesNotExist {
|
||||||
buffer.WriteString("!")
|
buffer.WriteString("!")
|
||||||
}
|
}
|
||||||
buffer.WriteString(r.key)
|
buffer.WriteString(r.key)
|
||||||
|
|
||||||
switch r.operator {
|
switch r.operator {
|
||||||
case EqualsOperator:
|
case selection.Equals:
|
||||||
buffer.WriteString("=")
|
buffer.WriteString("=")
|
||||||
case DoubleEqualsOperator:
|
case selection.DoubleEquals:
|
||||||
buffer.WriteString("==")
|
buffer.WriteString("==")
|
||||||
case NotEqualsOperator:
|
case selection.NotEquals:
|
||||||
buffer.WriteString("!=")
|
buffer.WriteString("!=")
|
||||||
case InOperator:
|
case selection.In:
|
||||||
buffer.WriteString(" in ")
|
buffer.WriteString(" in ")
|
||||||
case NotInOperator:
|
case selection.NotIn:
|
||||||
buffer.WriteString(" notin ")
|
buffer.WriteString(" notin ")
|
||||||
case GreaterThanOperator:
|
case selection.GreaterThan:
|
||||||
buffer.WriteString(">")
|
buffer.WriteString(">")
|
||||||
case LessThanOperator:
|
case selection.LessThan:
|
||||||
buffer.WriteString("<")
|
buffer.WriteString("<")
|
||||||
case ExistsOperator, DoesNotExistOperator:
|
case selection.Exists, selection.DoesNotExist:
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r.operator {
|
switch r.operator {
|
||||||
case InOperator, NotInOperator:
|
case selection.In, selection.NotIn:
|
||||||
buffer.WriteString("(")
|
buffer.WriteString("(")
|
||||||
}
|
}
|
||||||
if len(r.strValues) == 1 {
|
if len(r.strValues) == 1 {
|
||||||
@@ -270,7 +264,7 @@ func (r *Requirement) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch r.operator {
|
switch r.operator {
|
||||||
case InOperator, NotInOperator:
|
case selection.In, selection.NotIn:
|
||||||
buffer.WriteString(")")
|
buffer.WriteString(")")
|
||||||
}
|
}
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
@@ -301,6 +295,8 @@ func (lsel internalSelector) Matches(l Labels) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lsel internalSelector) Requirements() (Requirements, bool) { return Requirements(lsel), true }
|
||||||
|
|
||||||
// String returns a comma-separated string of all
|
// String returns a comma-separated string of all
|
||||||
// the internalSelector Requirements' human-readable strings.
|
// the internalSelector Requirements' human-readable strings.
|
||||||
func (lsel internalSelector) String() string {
|
func (lsel internalSelector) String() string {
|
||||||
@@ -564,7 +560,7 @@ func (p *Parser) parseRequirement() (*Requirement, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if operator == ExistsOperator || operator == DoesNotExistOperator { // operator found lookahead set checked
|
if operator == selection.Exists || operator == selection.DoesNotExist { // operator found lookahead set checked
|
||||||
return NewRequirement(key, operator, nil)
|
return NewRequirement(key, operator, nil)
|
||||||
}
|
}
|
||||||
operator, err = p.parseOperator()
|
operator, err = p.parseOperator()
|
||||||
@@ -573,9 +569,9 @@ func (p *Parser) parseRequirement() (*Requirement, error) {
|
|||||||
}
|
}
|
||||||
var values sets.String
|
var values sets.String
|
||||||
switch operator {
|
switch operator {
|
||||||
case InOperator, NotInOperator:
|
case selection.In, selection.NotIn:
|
||||||
values, err = p.parseValues()
|
values, err = p.parseValues()
|
||||||
case EqualsOperator, DoubleEqualsOperator, NotEqualsOperator, GreaterThanOperator, LessThanOperator:
|
case selection.Equals, selection.DoubleEquals, selection.NotEquals, selection.GreaterThan, selection.LessThan:
|
||||||
values, err = p.parseExactValue()
|
values, err = p.parseExactValue()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -588,11 +584,11 @@ func (p *Parser) parseRequirement() (*Requirement, error) {
|
|||||||
// parseKeyAndInferOperator parse literals.
|
// parseKeyAndInferOperator parse literals.
|
||||||
// in case of no operator '!, in, notin, ==, =, !=' are found
|
// in case of no operator '!, in, notin, ==, =, !=' are found
|
||||||
// the 'exists' operator is inferred
|
// the 'exists' operator is inferred
|
||||||
func (p *Parser) parseKeyAndInferOperator() (string, Operator, error) {
|
func (p *Parser) parseKeyAndInferOperator() (string, selection.Operator, error) {
|
||||||
var operator Operator
|
var operator selection.Operator
|
||||||
tok, literal := p.consume(Values)
|
tok, literal := p.consume(Values)
|
||||||
if tok == DoesNotExistToken {
|
if tok == DoesNotExistToken {
|
||||||
operator = DoesNotExistOperator
|
operator = selection.DoesNotExist
|
||||||
tok, literal = p.consume(Values)
|
tok, literal = p.consume(Values)
|
||||||
}
|
}
|
||||||
if tok != IdentifierToken {
|
if tok != IdentifierToken {
|
||||||
@@ -603,8 +599,8 @@ func (p *Parser) parseKeyAndInferOperator() (string, Operator, error) {
|
|||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
if t, _ := p.lookahead(Values); t == EndOfStringToken || t == CommaToken {
|
if t, _ := p.lookahead(Values); t == EndOfStringToken || t == CommaToken {
|
||||||
if operator != DoesNotExistOperator {
|
if operator != selection.DoesNotExist {
|
||||||
operator = ExistsOperator
|
operator = selection.Exists
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return literal, operator, nil
|
return literal, operator, nil
|
||||||
@@ -612,24 +608,24 @@ func (p *Parser) parseKeyAndInferOperator() (string, Operator, error) {
|
|||||||
|
|
||||||
// parseOperator return operator and eventually matchType
|
// parseOperator return operator and eventually matchType
|
||||||
// matchType can be exact
|
// matchType can be exact
|
||||||
func (p *Parser) parseOperator() (op Operator, err error) {
|
func (p *Parser) parseOperator() (op selection.Operator, err error) {
|
||||||
tok, lit := p.consume(KeyAndOperator)
|
tok, lit := p.consume(KeyAndOperator)
|
||||||
switch tok {
|
switch tok {
|
||||||
// DoesNotExistToken shouldn't be here because it's a unary operator, not a binary operator
|
// DoesNotExistToken shouldn't be here because it's a unary operator, not a binary operator
|
||||||
case InToken:
|
case InToken:
|
||||||
op = InOperator
|
op = selection.In
|
||||||
case EqualsToken:
|
case EqualsToken:
|
||||||
op = EqualsOperator
|
op = selection.Equals
|
||||||
case DoubleEqualsToken:
|
case DoubleEqualsToken:
|
||||||
op = DoubleEqualsOperator
|
op = selection.DoubleEquals
|
||||||
case GreaterThanToken:
|
case GreaterThanToken:
|
||||||
op = GreaterThanOperator
|
op = selection.GreaterThan
|
||||||
case LessThanToken:
|
case LessThanToken:
|
||||||
op = LessThanOperator
|
op = selection.LessThan
|
||||||
case NotInToken:
|
case NotInToken:
|
||||||
op = NotInOperator
|
op = selection.NotIn
|
||||||
case NotEqualsToken:
|
case NotEqualsToken:
|
||||||
op = NotEqualsOperator
|
op = selection.NotEquals
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("found '%s', expected: '=', '!=', '==', 'in', notin'", lit)
|
return "", fmt.Errorf("found '%s', expected: '=', '!=', '==', 'in', notin'", lit)
|
||||||
}
|
}
|
||||||
@@ -788,7 +784,7 @@ func SelectorFromSet(ls Set) Selector {
|
|||||||
}
|
}
|
||||||
var requirements internalSelector
|
var requirements internalSelector
|
||||||
for label, value := range ls {
|
for label, value := range ls {
|
||||||
if r, err := NewRequirement(label, EqualsOperator, sets.NewString(value)); err != nil {
|
if r, err := NewRequirement(label, selection.Equals, sets.NewString(value)); err != nil {
|
||||||
//TODO: double check errors when input comes from serialization?
|
//TODO: double check errors when input comes from serialization?
|
||||||
return internalSelector{}
|
return internalSelector{}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -21,6 +21,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/selection"
|
||||||
"k8s.io/kubernetes/pkg/util/sets"
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -300,23 +301,23 @@ func TestParserLookahead(t *testing.T) {
|
|||||||
func TestRequirementConstructor(t *testing.T) {
|
func TestRequirementConstructor(t *testing.T) {
|
||||||
requirementConstructorTests := []struct {
|
requirementConstructorTests := []struct {
|
||||||
Key string
|
Key string
|
||||||
Op Operator
|
Op selection.Operator
|
||||||
Vals sets.String
|
Vals sets.String
|
||||||
Success bool
|
Success bool
|
||||||
}{
|
}{
|
||||||
{"x", InOperator, nil, false},
|
{"x", selection.In, nil, false},
|
||||||
{"x", NotInOperator, sets.NewString(), false},
|
{"x", selection.NotIn, sets.NewString(), false},
|
||||||
{"x", InOperator, sets.NewString("foo"), true},
|
{"x", selection.In, sets.NewString("foo"), true},
|
||||||
{"x", NotInOperator, sets.NewString("foo"), true},
|
{"x", selection.NotIn, sets.NewString("foo"), true},
|
||||||
{"x", ExistsOperator, nil, true},
|
{"x", selection.Exists, nil, true},
|
||||||
{"x", DoesNotExistOperator, nil, true},
|
{"x", selection.DoesNotExist, nil, true},
|
||||||
{"1foo", InOperator, sets.NewString("bar"), true},
|
{"1foo", selection.In, sets.NewString("bar"), true},
|
||||||
{"1234", InOperator, sets.NewString("bar"), true},
|
{"1234", selection.In, sets.NewString("bar"), true},
|
||||||
{"y", GreaterThanOperator, sets.NewString("1"), true},
|
{"y", selection.GreaterThan, sets.NewString("1"), true},
|
||||||
{"z", LessThanOperator, sets.NewString("6"), true},
|
{"z", selection.LessThan, sets.NewString("6"), true},
|
||||||
{"foo", GreaterThanOperator, sets.NewString("bar"), false},
|
{"foo", selection.GreaterThan, sets.NewString("bar"), false},
|
||||||
{"barz", LessThanOperator, sets.NewString("blah"), false},
|
{"barz", selection.LessThan, sets.NewString("blah"), false},
|
||||||
{strings.Repeat("a", 254), ExistsOperator, nil, false}, //breaks DNS rule that len(key) <= 253
|
{strings.Repeat("a", 254), selection.Exists, nil, false}, //breaks DNS rule that len(key) <= 253
|
||||||
}
|
}
|
||||||
for _, rc := range requirementConstructorTests {
|
for _, rc := range requirementConstructorTests {
|
||||||
if _, err := NewRequirement(rc.Key, rc.Op, rc.Vals); err == nil && !rc.Success {
|
if _, err := NewRequirement(rc.Key, rc.Op, rc.Vals); err == nil && !rc.Success {
|
||||||
@@ -336,34 +337,34 @@ func TestToString(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
|
|
||||||
{&internalSelector{
|
{&internalSelector{
|
||||||
getRequirement("x", InOperator, sets.NewString("abc", "def"), t),
|
getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
|
||||||
getRequirement("y", NotInOperator, sets.NewString("jkl"), t),
|
getRequirement("y", selection.NotIn, sets.NewString("jkl"), t),
|
||||||
getRequirement("z", ExistsOperator, nil, t)},
|
getRequirement("z", selection.Exists, nil, t)},
|
||||||
"x in (abc,def),y notin (jkl),z", true},
|
"x in (abc,def),y notin (jkl),z", true},
|
||||||
{&internalSelector{
|
{&internalSelector{
|
||||||
getRequirement("x", NotInOperator, sets.NewString("abc", "def"), t),
|
getRequirement("x", selection.NotIn, sets.NewString("abc", "def"), t),
|
||||||
getRequirement("y", NotEqualsOperator, sets.NewString("jkl"), t),
|
getRequirement("y", selection.NotEquals, sets.NewString("jkl"), t),
|
||||||
getRequirement("z", DoesNotExistOperator, nil, t)},
|
getRequirement("z", selection.DoesNotExist, nil, t)},
|
||||||
"x notin (abc,def),y!=jkl,!z", true},
|
"x notin (abc,def),y!=jkl,!z", true},
|
||||||
{&internalSelector{
|
{&internalSelector{
|
||||||
getRequirement("x", InOperator, sets.NewString("abc", "def"), t),
|
getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
|
||||||
req}, // adding empty req for the trailing ','
|
req}, // adding empty req for the trailing ','
|
||||||
"x in (abc,def),", false},
|
"x in (abc,def),", false},
|
||||||
{&internalSelector{
|
{&internalSelector{
|
||||||
getRequirement("x", NotInOperator, sets.NewString("abc"), t),
|
getRequirement("x", selection.NotIn, sets.NewString("abc"), t),
|
||||||
getRequirement("y", InOperator, sets.NewString("jkl", "mno"), t),
|
getRequirement("y", selection.In, sets.NewString("jkl", "mno"), t),
|
||||||
getRequirement("z", NotInOperator, sets.NewString(""), t)},
|
getRequirement("z", selection.NotIn, sets.NewString(""), t)},
|
||||||
"x notin (abc),y in (jkl,mno),z notin ()", true},
|
"x notin (abc),y in (jkl,mno),z notin ()", true},
|
||||||
{&internalSelector{
|
{&internalSelector{
|
||||||
getRequirement("x", EqualsOperator, sets.NewString("abc"), t),
|
getRequirement("x", selection.Equals, sets.NewString("abc"), t),
|
||||||
getRequirement("y", DoubleEqualsOperator, sets.NewString("jkl"), t),
|
getRequirement("y", selection.DoubleEquals, sets.NewString("jkl"), t),
|
||||||
getRequirement("z", NotEqualsOperator, sets.NewString("a"), t),
|
getRequirement("z", selection.NotEquals, sets.NewString("a"), t),
|
||||||
getRequirement("z", ExistsOperator, nil, t)},
|
getRequirement("z", selection.Exists, nil, t)},
|
||||||
"x=abc,y==jkl,z!=a,z", true},
|
"x=abc,y==jkl,z!=a,z", true},
|
||||||
{&internalSelector{
|
{&internalSelector{
|
||||||
getRequirement("x", GreaterThanOperator, sets.NewString("2"), t),
|
getRequirement("x", selection.GreaterThan, sets.NewString("2"), t),
|
||||||
getRequirement("y", LessThanOperator, sets.NewString("8"), t),
|
getRequirement("y", selection.LessThan, sets.NewString("8"), t),
|
||||||
getRequirement("z", ExistsOperator, nil, t)},
|
getRequirement("z", selection.Exists, nil, t)},
|
||||||
"x>2,y<8,z", true},
|
"x>2,y<8,z", true},
|
||||||
}
|
}
|
||||||
for _, ts := range toStringTests {
|
for _, ts := range toStringTests {
|
||||||
@@ -386,33 +387,33 @@ func TestRequirementSelectorMatching(t *testing.T) {
|
|||||||
req,
|
req,
|
||||||
}, false},
|
}, false},
|
||||||
{Set{"x": "foo", "y": "baz"}, &internalSelector{
|
{Set{"x": "foo", "y": "baz"}, &internalSelector{
|
||||||
getRequirement("x", InOperator, sets.NewString("foo"), t),
|
getRequirement("x", selection.In, sets.NewString("foo"), t),
|
||||||
getRequirement("y", NotInOperator, sets.NewString("alpha"), t),
|
getRequirement("y", selection.NotIn, sets.NewString("alpha"), t),
|
||||||
}, true},
|
}, true},
|
||||||
{Set{"x": "foo", "y": "baz"}, &internalSelector{
|
{Set{"x": "foo", "y": "baz"}, &internalSelector{
|
||||||
getRequirement("x", InOperator, sets.NewString("foo"), t),
|
getRequirement("x", selection.In, sets.NewString("foo"), t),
|
||||||
getRequirement("y", InOperator, sets.NewString("alpha"), t),
|
getRequirement("y", selection.In, sets.NewString("alpha"), t),
|
||||||
}, false},
|
}, false},
|
||||||
{Set{"y": ""}, &internalSelector{
|
{Set{"y": ""}, &internalSelector{
|
||||||
getRequirement("x", NotInOperator, sets.NewString(""), t),
|
getRequirement("x", selection.NotIn, sets.NewString(""), t),
|
||||||
getRequirement("y", ExistsOperator, nil, t),
|
getRequirement("y", selection.Exists, nil, t),
|
||||||
}, true},
|
}, true},
|
||||||
{Set{"y": ""}, &internalSelector{
|
{Set{"y": ""}, &internalSelector{
|
||||||
getRequirement("x", DoesNotExistOperator, nil, t),
|
getRequirement("x", selection.DoesNotExist, nil, t),
|
||||||
getRequirement("y", ExistsOperator, nil, t),
|
getRequirement("y", selection.Exists, nil, t),
|
||||||
}, true},
|
}, true},
|
||||||
{Set{"y": ""}, &internalSelector{
|
{Set{"y": ""}, &internalSelector{
|
||||||
getRequirement("x", NotInOperator, sets.NewString(""), t),
|
getRequirement("x", selection.NotIn, sets.NewString(""), t),
|
||||||
getRequirement("y", DoesNotExistOperator, nil, t),
|
getRequirement("y", selection.DoesNotExist, nil, t),
|
||||||
}, false},
|
}, false},
|
||||||
{Set{"y": "baz"}, &internalSelector{
|
{Set{"y": "baz"}, &internalSelector{
|
||||||
getRequirement("x", InOperator, sets.NewString(""), t),
|
getRequirement("x", selection.In, sets.NewString(""), t),
|
||||||
}, false},
|
}, false},
|
||||||
{Set{"z": "2"}, &internalSelector{
|
{Set{"z": "2"}, &internalSelector{
|
||||||
getRequirement("z", GreaterThanOperator, sets.NewString("1"), t),
|
getRequirement("z", selection.GreaterThan, sets.NewString("1"), t),
|
||||||
}, true},
|
}, true},
|
||||||
{Set{"z": "v2"}, &internalSelector{
|
{Set{"z": "v2"}, &internalSelector{
|
||||||
getRequirement("z", GreaterThanOperator, sets.NewString("1"), t),
|
getRequirement("z", selection.GreaterThan, sets.NewString("1"), t),
|
||||||
}, false},
|
}, false},
|
||||||
}
|
}
|
||||||
for _, lsm := range labelSelectorMatchingTests {
|
for _, lsm := range labelSelectorMatchingTests {
|
||||||
@@ -431,80 +432,80 @@ func TestSetSelectorParser(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{"", NewSelector(), true, true},
|
{"", NewSelector(), true, true},
|
||||||
{"\rx", internalSelector{
|
{"\rx", internalSelector{
|
||||||
getRequirement("x", ExistsOperator, nil, t),
|
getRequirement("x", selection.Exists, nil, t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"this-is-a-dns.domain.com/key-with-dash", internalSelector{
|
{"this-is-a-dns.domain.com/key-with-dash", internalSelector{
|
||||||
getRequirement("this-is-a-dns.domain.com/key-with-dash", ExistsOperator, nil, t),
|
getRequirement("this-is-a-dns.domain.com/key-with-dash", selection.Exists, nil, t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"this-is-another-dns.domain.com/key-with-dash in (so,what)", internalSelector{
|
{"this-is-another-dns.domain.com/key-with-dash in (so,what)", internalSelector{
|
||||||
getRequirement("this-is-another-dns.domain.com/key-with-dash", InOperator, sets.NewString("so", "what"), t),
|
getRequirement("this-is-another-dns.domain.com/key-with-dash", selection.In, sets.NewString("so", "what"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"0.1.2.domain/99 notin (10.10.100.1, tick.tack.clock)", internalSelector{
|
{"0.1.2.domain/99 notin (10.10.100.1, tick.tack.clock)", internalSelector{
|
||||||
getRequirement("0.1.2.domain/99", NotInOperator, sets.NewString("10.10.100.1", "tick.tack.clock"), t),
|
getRequirement("0.1.2.domain/99", selection.NotIn, sets.NewString("10.10.100.1", "tick.tack.clock"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"foo in (abc)", internalSelector{
|
{"foo in (abc)", internalSelector{
|
||||||
getRequirement("foo", InOperator, sets.NewString("abc"), t),
|
getRequirement("foo", selection.In, sets.NewString("abc"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x notin\n (abc)", internalSelector{
|
{"x notin\n (abc)", internalSelector{
|
||||||
getRequirement("x", NotInOperator, sets.NewString("abc"), t),
|
getRequirement("x", selection.NotIn, sets.NewString("abc"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x notin \t (abc,def)", internalSelector{
|
{"x notin \t (abc,def)", internalSelector{
|
||||||
getRequirement("x", NotInOperator, sets.NewString("abc", "def"), t),
|
getRequirement("x", selection.NotIn, sets.NewString("abc", "def"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x in (abc,def)", internalSelector{
|
{"x in (abc,def)", internalSelector{
|
||||||
getRequirement("x", InOperator, sets.NewString("abc", "def"), t),
|
getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x in (abc,)", internalSelector{
|
{"x in (abc,)", internalSelector{
|
||||||
getRequirement("x", InOperator, sets.NewString("abc", ""), t),
|
getRequirement("x", selection.In, sets.NewString("abc", ""), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x in ()", internalSelector{
|
{"x in ()", internalSelector{
|
||||||
getRequirement("x", InOperator, sets.NewString(""), t),
|
getRequirement("x", selection.In, sets.NewString(""), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x notin (abc,,def),bar,z in (),w", internalSelector{
|
{"x notin (abc,,def),bar,z in (),w", internalSelector{
|
||||||
getRequirement("bar", ExistsOperator, nil, t),
|
getRequirement("bar", selection.Exists, nil, t),
|
||||||
getRequirement("w", ExistsOperator, nil, t),
|
getRequirement("w", selection.Exists, nil, t),
|
||||||
getRequirement("x", NotInOperator, sets.NewString("abc", "", "def"), t),
|
getRequirement("x", selection.NotIn, sets.NewString("abc", "", "def"), t),
|
||||||
getRequirement("z", InOperator, sets.NewString(""), t),
|
getRequirement("z", selection.In, sets.NewString(""), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x,y in (a)", internalSelector{
|
{"x,y in (a)", internalSelector{
|
||||||
getRequirement("y", InOperator, sets.NewString("a"), t),
|
getRequirement("y", selection.In, sets.NewString("a"), t),
|
||||||
getRequirement("x", ExistsOperator, nil, t),
|
getRequirement("x", selection.Exists, nil, t),
|
||||||
}, false, true},
|
}, false, true},
|
||||||
{"x=a", internalSelector{
|
{"x=a", internalSelector{
|
||||||
getRequirement("x", EqualsOperator, sets.NewString("a"), t),
|
getRequirement("x", selection.Equals, sets.NewString("a"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x>1", internalSelector{
|
{"x>1", internalSelector{
|
||||||
getRequirement("x", GreaterThanOperator, sets.NewString("1"), t),
|
getRequirement("x", selection.GreaterThan, sets.NewString("1"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x<7", internalSelector{
|
{"x<7", internalSelector{
|
||||||
getRequirement("x", LessThanOperator, sets.NewString("7"), t),
|
getRequirement("x", selection.LessThan, sets.NewString("7"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x=a,y!=b", internalSelector{
|
{"x=a,y!=b", internalSelector{
|
||||||
getRequirement("x", EqualsOperator, sets.NewString("a"), t),
|
getRequirement("x", selection.Equals, sets.NewString("a"), t),
|
||||||
getRequirement("y", NotEqualsOperator, sets.NewString("b"), t),
|
getRequirement("y", selection.NotEquals, sets.NewString("b"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x=a,y!=b,z in (h,i,j)", internalSelector{
|
{"x=a,y!=b,z in (h,i,j)", internalSelector{
|
||||||
getRequirement("x", EqualsOperator, sets.NewString("a"), t),
|
getRequirement("x", selection.Equals, sets.NewString("a"), t),
|
||||||
getRequirement("y", NotEqualsOperator, sets.NewString("b"), t),
|
getRequirement("y", selection.NotEquals, sets.NewString("b"), t),
|
||||||
getRequirement("z", InOperator, sets.NewString("h", "i", "j"), t),
|
getRequirement("z", selection.In, sets.NewString("h", "i", "j"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x=a||y=b", internalSelector{}, false, false},
|
{"x=a||y=b", internalSelector{}, false, false},
|
||||||
{"x,,y", nil, true, false},
|
{"x,,y", nil, true, false},
|
||||||
{",x,y", nil, true, false},
|
{",x,y", nil, true, false},
|
||||||
{"x nott in (y)", nil, true, false},
|
{"x nott in (y)", nil, true, false},
|
||||||
{"x notin ( )", internalSelector{
|
{"x notin ( )", internalSelector{
|
||||||
getRequirement("x", NotInOperator, sets.NewString(""), t),
|
getRequirement("x", selection.NotIn, sets.NewString(""), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"x notin (, a)", internalSelector{
|
{"x notin (, a)", internalSelector{
|
||||||
getRequirement("x", NotInOperator, sets.NewString("", "a"), t),
|
getRequirement("x", selection.NotIn, sets.NewString("", "a"), t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"a in (xyz),", nil, true, false},
|
{"a in (xyz),", nil, true, false},
|
||||||
{"a in (xyz)b notin ()", nil, true, false},
|
{"a in (xyz)b notin ()", nil, true, false},
|
||||||
{"a ", internalSelector{
|
{"a ", internalSelector{
|
||||||
getRequirement("a", ExistsOperator, nil, t),
|
getRequirement("a", selection.Exists, nil, t),
|
||||||
}, true, true},
|
}, true, true},
|
||||||
{"a in (x,y,notin, z,in)", internalSelector{
|
{"a in (x,y,notin, z,in)", internalSelector{
|
||||||
getRequirement("a", InOperator, sets.NewString("in", "notin", "x", "y", "z"), t),
|
getRequirement("a", selection.In, sets.NewString("in", "notin", "x", "y", "z"), t),
|
||||||
}, true, true}, // operator 'in' inside list of identifiers
|
}, true, true}, // operator 'in' inside list of identifiers
|
||||||
{"a in (xyz abc)", nil, false, false}, // no comma
|
{"a in (xyz abc)", nil, false, false}, // no comma
|
||||||
{"a notin(", nil, true, false}, // bad formed
|
{"a notin(", nil, true, false}, // bad formed
|
||||||
@@ -523,7 +524,7 @@ func TestSetSelectorParser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRequirement(key string, op Operator, vals sets.String, t *testing.T) Requirement {
|
func getRequirement(key string, op selection.Operator, vals sets.String, t *testing.T) Requirement {
|
||||||
req, err := NewRequirement(key, op, vals)
|
req, err := NewRequirement(key, op, vals)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("NewRequirement(%v, %v, %v) resulted in error:%v", key, op, vals, err)
|
t.Errorf("NewRequirement(%v, %v, %v) resulted in error:%v", key, op, vals, err)
|
||||||
@@ -537,7 +538,7 @@ func TestAdd(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
sel Selector
|
sel Selector
|
||||||
key string
|
key string
|
||||||
operator Operator
|
operator selection.Operator
|
||||||
values []string
|
values []string
|
||||||
refSelector Selector
|
refSelector Selector
|
||||||
}{
|
}{
|
||||||
@@ -545,19 +546,19 @@ func TestAdd(t *testing.T) {
|
|||||||
"keyInOperator",
|
"keyInOperator",
|
||||||
internalSelector{},
|
internalSelector{},
|
||||||
"key",
|
"key",
|
||||||
InOperator,
|
selection.In,
|
||||||
[]string{"value"},
|
[]string{"value"},
|
||||||
internalSelector{Requirement{"key", InOperator, sets.NewString("value")}},
|
internalSelector{Requirement{"key", selection.In, sets.NewString("value")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"keyEqualsOperator",
|
"keyEqualsOperator",
|
||||||
internalSelector{Requirement{"key", InOperator, sets.NewString("value")}},
|
internalSelector{Requirement{"key", selection.In, sets.NewString("value")}},
|
||||||
"key2",
|
"key2",
|
||||||
EqualsOperator,
|
selection.Equals,
|
||||||
[]string{"value2"},
|
[]string{"value2"},
|
||||||
internalSelector{
|
internalSelector{
|
||||||
Requirement{"key", InOperator, sets.NewString("value")},
|
Requirement{"key", selection.In, sets.NewString("value")},
|
||||||
Requirement{"key2", EqualsOperator, sets.NewString("value2")},
|
Requirement{"key2", selection.Equals, sets.NewString("value2")},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/registry/generic"
|
"k8s.io/kubernetes/pkg/registry/generic"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
|
"k8s.io/kubernetes/pkg/selection"
|
||||||
"k8s.io/kubernetes/pkg/storage"
|
"k8s.io/kubernetes/pkg/storage"
|
||||||
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
|
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
|
||||||
"k8s.io/kubernetes/pkg/storage/etcd/etcdtest"
|
"k8s.io/kubernetes/pkg/storage/etcd/etcdtest"
|
||||||
@@ -88,7 +89,7 @@ func NewTestGenericStoreRegistry(t *testing.T) (*etcdtesting.EtcdTestServer, *St
|
|||||||
func matchPodName(names ...string) *generic.SelectionPredicate {
|
func matchPodName(names ...string) *generic.SelectionPredicate {
|
||||||
// Note: even if pod name is a field, we have to use labels,
|
// Note: even if pod name is a field, we have to use labels,
|
||||||
// because field selector doesn't support "IN" operator.
|
// because field selector doesn't support "IN" operator.
|
||||||
l, err := labels.NewRequirement("name", labels.InOperator, sets.NewString(names...))
|
l, err := labels.NewRequirement("name", selection.In, sets.NewString(names...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Labels requirement must validate successfully")
|
panic("Labels requirement must validate successfully")
|
||||||
}
|
}
|
||||||
|
33
pkg/selection/operator.go
Normal file
33
pkg/selection/operator.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package selection
|
||||||
|
|
||||||
|
// Operator represents a key/field's relationship to value(s).
|
||||||
|
// See labels.Requirement and fields.Requirement for more details.
|
||||||
|
type Operator string
|
||||||
|
|
||||||
|
const (
|
||||||
|
DoesNotExist Operator = "!"
|
||||||
|
Equals Operator = "="
|
||||||
|
DoubleEquals Operator = "=="
|
||||||
|
In Operator = "in"
|
||||||
|
NotEquals Operator = "!="
|
||||||
|
NotIn Operator = "notin"
|
||||||
|
Exists Operator = "exists"
|
||||||
|
GreaterThan Operator = "gt"
|
||||||
|
LessThan Operator = "lt"
|
||||||
|
)
|
Reference in New Issue
Block a user