k8s.io/client-go@v0.22.2/tools/cache/listers.go (about) 1 /* 2 Copyright 2014 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 cache 18 19 import ( 20 "k8s.io/klog/v2" 21 22 "k8s.io/apimachinery/pkg/api/errors" 23 "k8s.io/apimachinery/pkg/api/meta" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/labels" 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/apimachinery/pkg/runtime/schema" 28 ) 29 30 // AppendFunc is used to add a matching item to whatever list the caller is using 31 type AppendFunc func(interface{}) 32 33 // ListAll calls appendFn with each value retrieved from store which matches the selector. 34 func ListAll(store Store, selector labels.Selector, appendFn AppendFunc) error { 35 selectAll := selector.Empty() 36 for _, m := range store.List() { 37 if selectAll { 38 // Avoid computing labels of the objects to speed up common flows 39 // of listing all objects. 40 appendFn(m) 41 continue 42 } 43 metadata, err := meta.Accessor(m) 44 if err != nil { 45 return err 46 } 47 if selector.Matches(labels.Set(metadata.GetLabels())) { 48 appendFn(m) 49 } 50 } 51 return nil 52 } 53 54 // ListAllByNamespace used to list items belongs to namespace from Indexer. 55 func ListAllByNamespace(indexer Indexer, namespace string, selector labels.Selector, appendFn AppendFunc) error { 56 selectAll := selector.Empty() 57 if namespace == metav1.NamespaceAll { 58 for _, m := range indexer.List() { 59 if selectAll { 60 // Avoid computing labels of the objects to speed up common flows 61 // of listing all objects. 62 appendFn(m) 63 continue 64 } 65 metadata, err := meta.Accessor(m) 66 if err != nil { 67 return err 68 } 69 if selector.Matches(labels.Set(metadata.GetLabels())) { 70 appendFn(m) 71 } 72 } 73 return nil 74 } 75 76 items, err := indexer.Index(NamespaceIndex, &metav1.ObjectMeta{Namespace: namespace}) 77 if err != nil { 78 // Ignore error; do slow search without index. 79 klog.Warningf("can not retrieve list of objects using index : %v", err) 80 for _, m := range indexer.List() { 81 metadata, err := meta.Accessor(m) 82 if err != nil { 83 return err 84 } 85 if metadata.GetNamespace() == namespace && selector.Matches(labels.Set(metadata.GetLabels())) { 86 appendFn(m) 87 } 88 89 } 90 return nil 91 } 92 for _, m := range items { 93 if selectAll { 94 // Avoid computing labels of the objects to speed up common flows 95 // of listing all objects. 96 appendFn(m) 97 continue 98 } 99 metadata, err := meta.Accessor(m) 100 if err != nil { 101 return err 102 } 103 if selector.Matches(labels.Set(metadata.GetLabels())) { 104 appendFn(m) 105 } 106 } 107 108 return nil 109 } 110 111 // GenericLister is a lister skin on a generic Indexer 112 type GenericLister interface { 113 // List will return all objects across namespaces 114 List(selector labels.Selector) (ret []runtime.Object, err error) 115 // Get will attempt to retrieve assuming that name==key 116 Get(name string) (runtime.Object, error) 117 // ByNamespace will give you a GenericNamespaceLister for one namespace 118 ByNamespace(namespace string) GenericNamespaceLister 119 } 120 121 // GenericNamespaceLister is a lister skin on a generic Indexer 122 type GenericNamespaceLister interface { 123 // List will return all objects in this namespace 124 List(selector labels.Selector) (ret []runtime.Object, err error) 125 // Get will attempt to retrieve by namespace and name 126 Get(name string) (runtime.Object, error) 127 } 128 129 // NewGenericLister creates a new instance for the genericLister. 130 func NewGenericLister(indexer Indexer, resource schema.GroupResource) GenericLister { 131 return &genericLister{indexer: indexer, resource: resource} 132 } 133 134 type genericLister struct { 135 indexer Indexer 136 resource schema.GroupResource 137 } 138 139 func (s *genericLister) List(selector labels.Selector) (ret []runtime.Object, err error) { 140 err = ListAll(s.indexer, selector, func(m interface{}) { 141 ret = append(ret, m.(runtime.Object)) 142 }) 143 return ret, err 144 } 145 146 func (s *genericLister) ByNamespace(namespace string) GenericNamespaceLister { 147 return &genericNamespaceLister{indexer: s.indexer, namespace: namespace, resource: s.resource} 148 } 149 150 func (s *genericLister) Get(name string) (runtime.Object, error) { 151 obj, exists, err := s.indexer.GetByKey(name) 152 if err != nil { 153 return nil, err 154 } 155 if !exists { 156 return nil, errors.NewNotFound(s.resource, name) 157 } 158 return obj.(runtime.Object), nil 159 } 160 161 type genericNamespaceLister struct { 162 indexer Indexer 163 namespace string 164 resource schema.GroupResource 165 } 166 167 func (s *genericNamespaceLister) List(selector labels.Selector) (ret []runtime.Object, err error) { 168 err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 169 ret = append(ret, m.(runtime.Object)) 170 }) 171 return ret, err 172 } 173 174 func (s *genericNamespaceLister) Get(name string) (runtime.Object, error) { 175 obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 176 if err != nil { 177 return nil, err 178 } 179 if !exists { 180 return nil, errors.NewNotFound(s.resource, name) 181 } 182 return obj.(runtime.Object), nil 183 }