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  }