mirror of https://github.com/k3s-io/k3s
make labels, fields expose selectable requirements
parent
9030a3234f
commit
1871a22039
|
@ -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:
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -50,32 +60,17 @@ func Everything() Selector {
|
||||||
|
|
||||||
type nothingSelector struct{}
|
type nothingSelector struct{}
|
||||||
|
|
||||||
func (n nothingSelector) Matches(_ Labels) bool { return false }
|
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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
)
|
Loading…
Reference in New Issue