k3s/vendor/k8s.io/apiserver/pkg/storage/selection_predicate.go

160 lines
4.7 KiB
Go
Raw Normal View History

2019-01-12 04:58:27 +00:00
/*
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 storage
import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
)
// AttrFunc returns label and field sets and the uninitialized flag for List or Watch to match.
// In any failure to parse given object, it returns error.
2019-04-07 17:07:55 +00:00
type AttrFunc func(obj runtime.Object) (labels.Set, fields.Set, error)
2019-01-12 04:58:27 +00:00
// FieldMutationFunc allows the mutation of the field selection fields. It is mutating to
// avoid the extra allocation on this common path
type FieldMutationFunc func(obj runtime.Object, fieldSet fields.Set) error
2019-04-07 17:07:55 +00:00
func DefaultClusterScopedAttr(obj runtime.Object) (labels.Set, fields.Set, error) {
2019-01-12 04:58:27 +00:00
metadata, err := meta.Accessor(obj)
if err != nil {
2019-04-07 17:07:55 +00:00
return nil, nil, err
2019-01-12 04:58:27 +00:00
}
fieldSet := fields.Set{
"metadata.name": metadata.GetName(),
}
2019-04-07 17:07:55 +00:00
return labels.Set(metadata.GetLabels()), fieldSet, nil
2019-01-12 04:58:27 +00:00
}
2019-04-07 17:07:55 +00:00
func DefaultNamespaceScopedAttr(obj runtime.Object) (labels.Set, fields.Set, error) {
2019-01-12 04:58:27 +00:00
metadata, err := meta.Accessor(obj)
if err != nil {
2019-04-07 17:07:55 +00:00
return nil, nil, err
2019-01-12 04:58:27 +00:00
}
fieldSet := fields.Set{
"metadata.name": metadata.GetName(),
"metadata.namespace": metadata.GetNamespace(),
}
2019-04-07 17:07:55 +00:00
return labels.Set(metadata.GetLabels()), fieldSet, nil
2019-01-12 04:58:27 +00:00
}
func (f AttrFunc) WithFieldMutation(fieldMutator FieldMutationFunc) AttrFunc {
2019-04-07 17:07:55 +00:00
return func(obj runtime.Object) (labels.Set, fields.Set, error) {
labelSet, fieldSet, err := f(obj)
2019-01-12 04:58:27 +00:00
if err != nil {
2019-04-07 17:07:55 +00:00
return nil, nil, err
2019-01-12 04:58:27 +00:00
}
if err := fieldMutator(obj, fieldSet); err != nil {
2019-04-07 17:07:55 +00:00
return nil, nil, err
2019-01-12 04:58:27 +00:00
}
2019-04-07 17:07:55 +00:00
return labelSet, fieldSet, nil
2019-01-12 04:58:27 +00:00
}
}
// SelectionPredicate is used to represent the way to select objects from api storage.
type SelectionPredicate struct {
2019-08-30 18:33:25 +00:00
Label labels.Selector
Field fields.Selector
GetAttrs AttrFunc
2020-03-26 21:07:15 +00:00
IndexLabels []string
2019-08-30 18:33:25 +00:00
IndexFields []string
Limit int64
Continue string
AllowWatchBookmarks bool
2019-01-12 04:58:27 +00:00
}
// Matches returns true if the given object's labels and fields (as
// returned by s.GetAttrs) match s.Label and s.Field. An error is
// returned if s.GetAttrs fails.
func (s *SelectionPredicate) Matches(obj runtime.Object) (bool, error) {
if s.Empty() {
return true, nil
}
2019-04-07 17:07:55 +00:00
labels, fields, err := s.GetAttrs(obj)
2019-01-12 04:58:27 +00:00
if err != nil {
return false, err
}
matched := s.Label.Matches(labels)
if matched && s.Field != nil {
matched = matched && s.Field.Matches(fields)
}
return matched, nil
}
// MatchesObjectAttributes returns true if the given labels and fields
// match s.Label and s.Field.
2019-04-07 17:07:55 +00:00
func (s *SelectionPredicate) MatchesObjectAttributes(l labels.Set, f fields.Set) bool {
2019-01-12 04:58:27 +00:00
if s.Label.Empty() && s.Field.Empty() {
return true
}
matched := s.Label.Matches(l)
if matched && s.Field != nil {
matched = (matched && s.Field.Matches(f))
}
return matched
}
// MatchesSingle will return (name, true) if and only if s.Field matches on the object's
// name.
func (s *SelectionPredicate) MatchesSingle() (string, bool) {
if len(s.Continue) > 0 {
return "", false
}
// TODO: should be namespace.name
if name, ok := s.Field.RequiresExactMatch("metadata.name"); ok {
return name, true
}
return "", false
}
// Empty returns true if the predicate performs no filtering.
func (s *SelectionPredicate) Empty() bool {
2019-04-07 17:07:55 +00:00
return s.Label.Empty() && s.Field.Empty()
2019-01-12 04:58:27 +00:00
}
2020-03-26 21:07:15 +00:00
// For any index defined by IndexFields, if a matcher can match only (a subset)
// of objects that return <value> for a given index, a pair (<index name>, <value>)
// wil be returned.
func (s *SelectionPredicate) MatcherIndex() []MatchValue {
var result []MatchValue
for _, field := range s.IndexFields {
if value, ok := s.Field.RequiresExactMatch(field); ok {
result = append(result, MatchValue{IndexName: FieldIndex(field), Value: value})
}
}
for _, label := range s.IndexLabels {
if value, ok := s.Label.RequiresExactMatch(label); ok {
result = append(result, MatchValue{IndexName: LabelIndex(label), Value: value})
}
}
return result
}
// LabelIndex add prefix for label index.
func LabelIndex(label string) string {
return "l:" + label
}
// FiledIndex add prefix for field index.
func FieldIndex(field string) string {
return "f:" + field
}