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  }