k8s.io/apiserver@v0.29.3/pkg/storage/selection_predicate.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package storage 18 19 import ( 20 "k8s.io/apimachinery/pkg/api/meta" 21 "k8s.io/apimachinery/pkg/fields" 22 "k8s.io/apimachinery/pkg/labels" 23 "k8s.io/apimachinery/pkg/runtime" 24 ) 25 26 // AttrFunc returns label and field sets and the uninitialized flag for List or Watch to match. 27 // In any failure to parse given object, it returns error. 28 type AttrFunc func(obj runtime.Object) (labels.Set, fields.Set, error) 29 30 // FieldMutationFunc allows the mutation of the field selection fields. It is mutating to 31 // avoid the extra allocation on this common path 32 type FieldMutationFunc func(obj runtime.Object, fieldSet fields.Set) error 33 34 func DefaultClusterScopedAttr(obj runtime.Object) (labels.Set, fields.Set, error) { 35 metadata, err := meta.Accessor(obj) 36 if err != nil { 37 return nil, nil, err 38 } 39 fieldSet := fields.Set{ 40 "metadata.name": metadata.GetName(), 41 } 42 43 return labels.Set(metadata.GetLabels()), fieldSet, nil 44 } 45 46 func DefaultNamespaceScopedAttr(obj runtime.Object) (labels.Set, fields.Set, error) { 47 metadata, err := meta.Accessor(obj) 48 if err != nil { 49 return nil, nil, err 50 } 51 fieldSet := fields.Set{ 52 "metadata.name": metadata.GetName(), 53 "metadata.namespace": metadata.GetNamespace(), 54 } 55 56 return labels.Set(metadata.GetLabels()), fieldSet, nil 57 } 58 59 func (f AttrFunc) WithFieldMutation(fieldMutator FieldMutationFunc) AttrFunc { 60 return func(obj runtime.Object) (labels.Set, fields.Set, error) { 61 labelSet, fieldSet, err := f(obj) 62 if err != nil { 63 return nil, nil, err 64 } 65 if err := fieldMutator(obj, fieldSet); err != nil { 66 return nil, nil, err 67 } 68 return labelSet, fieldSet, nil 69 } 70 } 71 72 // SelectionPredicate is used to represent the way to select objects from api storage. 73 type SelectionPredicate struct { 74 Label labels.Selector 75 Field fields.Selector 76 GetAttrs AttrFunc 77 IndexLabels []string 78 IndexFields []string 79 Limit int64 80 Continue string 81 AllowWatchBookmarks bool 82 } 83 84 // Matches returns true if the given object's labels and fields (as 85 // returned by s.GetAttrs) match s.Label and s.Field. An error is 86 // returned if s.GetAttrs fails. 87 func (s *SelectionPredicate) Matches(obj runtime.Object) (bool, error) { 88 if s.Empty() { 89 return true, nil 90 } 91 labels, fields, err := s.GetAttrs(obj) 92 if err != nil { 93 return false, err 94 } 95 matched := s.Label.Matches(labels) 96 if matched && s.Field != nil { 97 matched = matched && s.Field.Matches(fields) 98 } 99 return matched, nil 100 } 101 102 // MatchesObjectAttributes returns true if the given labels and fields 103 // match s.Label and s.Field. 104 func (s *SelectionPredicate) MatchesObjectAttributes(l labels.Set, f fields.Set) bool { 105 if s.Label.Empty() && s.Field.Empty() { 106 return true 107 } 108 matched := s.Label.Matches(l) 109 if matched && s.Field != nil { 110 matched = (matched && s.Field.Matches(f)) 111 } 112 return matched 113 } 114 115 // MatchesSingleNamespace will return (namespace, true) if and only if s.Field matches on the object's 116 // namespace. 117 func (s *SelectionPredicate) MatchesSingleNamespace() (string, bool) { 118 if len(s.Continue) > 0 { 119 return "", false 120 } 121 if namespace, ok := s.Field.RequiresExactMatch("metadata.namespace"); ok { 122 return namespace, true 123 } 124 return "", false 125 } 126 127 // MatchesSingle will return (name, true) if and only if s.Field matches on the object's 128 // name. 129 func (s *SelectionPredicate) MatchesSingle() (string, bool) { 130 if len(s.Continue) > 0 { 131 return "", false 132 } 133 // TODO: should be namespace.name 134 if name, ok := s.Field.RequiresExactMatch("metadata.name"); ok { 135 return name, true 136 } 137 return "", false 138 } 139 140 // Empty returns true if the predicate performs no filtering. 141 func (s *SelectionPredicate) Empty() bool { 142 return s.Label.Empty() && s.Field.Empty() 143 } 144 145 // For any index defined by IndexFields, if a matcher can match only (a subset) 146 // of objects that return <value> for a given index, a pair (<index name>, <value>) 147 // wil be returned. 148 func (s *SelectionPredicate) MatcherIndex() []MatchValue { 149 var result []MatchValue 150 for _, field := range s.IndexFields { 151 if value, ok := s.Field.RequiresExactMatch(field); ok { 152 result = append(result, MatchValue{IndexName: FieldIndex(field), Value: value}) 153 } 154 } 155 for _, label := range s.IndexLabels { 156 if value, ok := s.Label.RequiresExactMatch(label); ok { 157 result = append(result, MatchValue{IndexName: LabelIndex(label), Value: value}) 158 } 159 } 160 return result 161 } 162 163 // LabelIndex add prefix for label index. 164 func LabelIndex(label string) string { 165 return "l:" + label 166 } 167 168 // FiledIndex add prefix for field index. 169 func FieldIndex(field string) string { 170 return "f:" + field 171 }