github.com/cilium/cilium@v1.16.2/pkg/k8s/resource/store.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package resource
     5  
     6  import (
     7  	corev1 "k8s.io/api/core/v1"
     8  	k8sRuntime "k8s.io/apimachinery/pkg/runtime"
     9  	"k8s.io/client-go/tools/cache"
    10  )
    11  
    12  // Store is a read-only typed wrapper for cache.Store.
    13  type Store[T k8sRuntime.Object] interface {
    14  	// List returns all items currently in the store.
    15  	List() []T
    16  
    17  	// IterKeys returns a key iterator.
    18  	IterKeys() KeyIter
    19  
    20  	// Get returns the latest version by deriving the key from the given object.
    21  	Get(obj T) (item T, exists bool, err error)
    22  
    23  	// GetByKey returns the latest version of the object with given key.
    24  	GetByKey(key Key) (item T, exists bool, err error)
    25  
    26  	// IndexKeys returns the keys of the stored objects whose set of indexed values
    27  	// for the index includes the given indexed value.
    28  	IndexKeys(indexName, indexedValue string) ([]string, error)
    29  
    30  	// ByIndex returns the stored objects whose set of indexed values for the index
    31  	// includes the given indexed value.
    32  	ByIndex(indexName, indexedValue string) ([]T, error)
    33  
    34  	// CacheStore returns the underlying cache.Store instance. Use for temporary
    35  	// compatibility purposes only!
    36  	CacheStore() cache.Store
    37  
    38  	// Release the store and allows the associated resource to stop its informer if
    39  	// this is the last reference to it.
    40  	// This is a no-op if the resource is not releasable.
    41  	Release()
    42  }
    43  
    44  // typedStore implements Store on top of an untyped cache.Indexer.
    45  type typedStore[T k8sRuntime.Object] struct {
    46  	store   cache.Indexer
    47  	release func()
    48  }
    49  
    50  var _ Store[*corev1.Node] = &typedStore[*corev1.Node]{}
    51  
    52  func (s *typedStore[T]) List() []T {
    53  	items := s.store.List()
    54  	result := make([]T, len(items))
    55  	for i := range items {
    56  		result[i] = items[i].(T)
    57  	}
    58  	return result
    59  }
    60  
    61  func (s *typedStore[T]) IterKeys() KeyIter {
    62  	return &keyIterImpl{keys: s.store.ListKeys(), pos: -1}
    63  }
    64  
    65  func (s *typedStore[T]) Get(obj T) (item T, exists bool, err error) {
    66  	return s.GetByKey(NewKey(obj))
    67  }
    68  
    69  func (s *typedStore[T]) GetByKey(key Key) (item T, exists bool, err error) {
    70  	var itemAny any
    71  	itemAny, exists, err = s.store.GetByKey(key.String())
    72  	if exists {
    73  		item = itemAny.(T)
    74  	}
    75  	return
    76  }
    77  
    78  func (s *typedStore[T]) IndexKeys(indexName, indexedValue string) ([]string, error) {
    79  	return s.store.IndexKeys(indexName, indexedValue)
    80  }
    81  
    82  func (s *typedStore[T]) ByIndex(indexName, indexedValue string) ([]T, error) {
    83  	itemsAny, err := s.store.ByIndex(indexName, indexedValue)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	items := make([]T, 0, len(itemsAny))
    88  	for _, item := range itemsAny {
    89  		items = append(items, item.(T))
    90  	}
    91  	return items, nil
    92  }
    93  
    94  func (s *typedStore[T]) CacheStore() cache.Store {
    95  	return s.store
    96  }
    97  
    98  func (s *typedStore[T]) Release() {
    99  	s.release()
   100  }
   101  
   102  type KeyIter interface {
   103  	// Next returns true if there is a key, false if iteration has finished.
   104  	Next() bool
   105  	Key() Key
   106  }
   107  
   108  type keyIterImpl struct {
   109  	keys []string
   110  	pos  int
   111  }
   112  
   113  func (it *keyIterImpl) Next() bool {
   114  	it.pos++
   115  	return it.pos < len(it.keys)
   116  }
   117  
   118  func (it *keyIterImpl) Key() Key {
   119  	ns, name, _ := cache.SplitMetaNamespaceKey(it.keys[it.pos])
   120  	// ignoring error from SplitMetaNamespaceKey as the string is from
   121  	// the cache.
   122  	return Key{Namespace: ns, Name: name}
   123  }