...

Source file src/k8s.io/client-go/tools/cache/listers.go

Documentation: k8s.io/client-go/tools/cache

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

View as plain text