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 }