Commit 1871a220 authored by Hongchao Deng's avatar Hongchao Deng

make labels, fields expose selectable requirements

parent 9030a323
...@@ -30,6 +30,7 @@ import ( ...@@ -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 ...@@ -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 ( ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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:
......
/*
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 ( ...@@ -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 { ...@@ -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) { ...@@ -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) { ...@@ -103,6 +117,14 @@ func (t *notHasTerm) Transform(fn TransformFunc) (Selector, error) {
return &notHasTerm{field, value}, nil return &notHasTerm{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) { ...@@ -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 {
......
...@@ -35,6 +35,7 @@ import ( ...@@ -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 ...@@ -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")
} }
......
/*
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"
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment