k8s.io/client-go@v0.31.1/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 lists items in the store matching the given selector, calling appendFn on each one. 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 lists items in the given namespace in the store matching the given selector, 55 // calling appendFn on each one. 56 // If a blank namespace (NamespaceAll) is specified, this delegates to ListAll(). 57 func ListAllByNamespace(indexer Indexer, namespace string, selector labels.Selector, appendFn AppendFunc) error { 58 if namespace == metav1.NamespaceAll { 59 return ListAll(indexer, selector, appendFn) 60 } 61 62 items, err := indexer.Index(NamespaceIndex, &metav1.ObjectMeta{Namespace: namespace}) 63 if err != nil { 64 // Ignore error; do slow search without index. 65 klog.Warningf("can not retrieve list of objects using index : %v", err) 66 for _, m := range indexer.List() { 67 metadata, err := meta.Accessor(m) 68 if err != nil { 69 return err 70 } 71 if metadata.GetNamespace() == namespace && selector.Matches(labels.Set(metadata.GetLabels())) { 72 appendFn(m) 73 } 74 75 } 76 return nil 77 } 78 79 selectAll := selector.Empty() 80 for _, m := range items { 81 if selectAll { 82 // Avoid computing labels of the objects to speed up common flows 83 // of listing all objects. 84 appendFn(m) 85 continue 86 } 87 metadata, err := meta.Accessor(m) 88 if err != nil { 89 return err 90 } 91 if selector.Matches(labels.Set(metadata.GetLabels())) { 92 appendFn(m) 93 } 94 } 95 96 return nil 97 } 98 99 // GenericLister is a lister skin on a generic Indexer 100 type GenericLister interface { 101 // List will return all objects across namespaces 102 List(selector labels.Selector) (ret []runtime.Object, err error) 103 // Get will attempt to retrieve assuming that name==key 104 Get(name string) (runtime.Object, error) 105 // ByNamespace will give you a GenericNamespaceLister for one namespace 106 ByNamespace(namespace string) GenericNamespaceLister 107 } 108 109 // GenericNamespaceLister is a lister skin on a generic Indexer 110 type GenericNamespaceLister interface { 111 // List will return all objects in this namespace 112 List(selector labels.Selector) (ret []runtime.Object, err error) 113 // Get will attempt to retrieve by namespace and name 114 Get(name string) (runtime.Object, error) 115 } 116 117 // NewGenericLister creates a new instance for the genericLister. 118 func NewGenericLister(indexer Indexer, resource schema.GroupResource) GenericLister { 119 return &genericLister{indexer: indexer, resource: resource} 120 } 121 122 type genericLister struct { 123 indexer Indexer 124 resource schema.GroupResource 125 } 126 127 func (s *genericLister) List(selector labels.Selector) (ret []runtime.Object, err error) { 128 err = ListAll(s.indexer, selector, func(m interface{}) { 129 ret = append(ret, m.(runtime.Object)) 130 }) 131 return ret, err 132 } 133 134 func (s *genericLister) ByNamespace(namespace string) GenericNamespaceLister { 135 return &genericNamespaceLister{indexer: s.indexer, namespace: namespace, resource: s.resource} 136 } 137 138 func (s *genericLister) Get(name string) (runtime.Object, error) { 139 obj, exists, err := s.indexer.GetByKey(name) 140 if err != nil { 141 return nil, err 142 } 143 if !exists { 144 return nil, errors.NewNotFound(s.resource, name) 145 } 146 return obj.(runtime.Object), nil 147 } 148 149 type genericNamespaceLister struct { 150 indexer Indexer 151 namespace string 152 resource schema.GroupResource 153 } 154 155 func (s *genericNamespaceLister) List(selector labels.Selector) (ret []runtime.Object, err error) { 156 err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 157 ret = append(ret, m.(runtime.Object)) 158 }) 159 return ret, err 160 } 161 162 func (s *genericNamespaceLister) Get(name string) (runtime.Object, error) { 163 obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 164 if err != nil { 165 return nil, err 166 } 167 if !exists { 168 return nil, errors.NewNotFound(s.resource, name) 169 } 170 return obj.(runtime.Object), nil 171 }