...

Source file src/k8s.io/client-go/tools/cache/store.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  	"fmt"
    21  	"strings"
    22  
    23  	"k8s.io/apimachinery/pkg/api/meta"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  )
    26  
    27  // Store is a generic object storage and processing interface.  A
    28  // Store holds a map from string keys to accumulators, and has
    29  // operations to add, update, and delete a given object to/from the
    30  // accumulator currently associated with a given key.  A Store also
    31  // knows how to extract the key from a given object, so many operations
    32  // are given only the object.
    33  //
    34  // In the simplest Store implementations each accumulator is simply
    35  // the last given object, or empty after Delete, and thus the Store's
    36  // behavior is simple storage.
    37  //
    38  // Reflector knows how to watch a server and update a Store.  This
    39  // package provides a variety of implementations of Store.
    40  type Store interface {
    41  
    42  	// Add adds the given object to the accumulator associated with the given object's key
    43  	Add(obj interface{}) error
    44  
    45  	// Update updates the given object in the accumulator associated with the given object's key
    46  	Update(obj interface{}) error
    47  
    48  	// Delete deletes the given object from the accumulator associated with the given object's key
    49  	Delete(obj interface{}) error
    50  
    51  	// List returns a list of all the currently non-empty accumulators
    52  	List() []interface{}
    53  
    54  	// ListKeys returns a list of all the keys currently associated with non-empty accumulators
    55  	ListKeys() []string
    56  
    57  	// Get returns the accumulator associated with the given object's key
    58  	Get(obj interface{}) (item interface{}, exists bool, err error)
    59  
    60  	// GetByKey returns the accumulator associated with the given key
    61  	GetByKey(key string) (item interface{}, exists bool, err error)
    62  
    63  	// Replace will delete the contents of the store, using instead the
    64  	// given list. Store takes ownership of the list, you should not reference
    65  	// it after calling this function.
    66  	Replace([]interface{}, string) error
    67  
    68  	// Resync is meaningless in the terms appearing here but has
    69  	// meaning in some implementations that have non-trivial
    70  	// additional behavior (e.g., DeltaFIFO).
    71  	Resync() error
    72  }
    73  
    74  // KeyFunc knows how to make a key from an object. Implementations should be deterministic.
    75  type KeyFunc func(obj interface{}) (string, error)
    76  
    77  // KeyError will be returned any time a KeyFunc gives an error; it includes the object
    78  // at fault.
    79  type KeyError struct {
    80  	Obj interface{}
    81  	Err error
    82  }
    83  
    84  // Error gives a human-readable description of the error.
    85  func (k KeyError) Error() string {
    86  	return fmt.Sprintf("couldn't create key for object %+v: %v", k.Obj, k.Err)
    87  }
    88  
    89  // Unwrap implements errors.Unwrap
    90  func (k KeyError) Unwrap() error {
    91  	return k.Err
    92  }
    93  
    94  // ExplicitKey can be passed to MetaNamespaceKeyFunc if you have the key for
    95  // the object but not the object itself.
    96  type ExplicitKey string
    97  
    98  // MetaNamespaceKeyFunc is a convenient default KeyFunc which knows how to make
    99  // keys for API objects which implement meta.Interface.
   100  // The key uses the format <namespace>/<name> unless <namespace> is empty, then
   101  // it's just <name>.
   102  //
   103  // Clients that want a structured alternative can use ObjectToName or MetaObjectToName.
   104  // Note: this would not be a client that wants a key for a Store because those are
   105  // necessarily strings.
   106  //
   107  // TODO maybe some day?: change Store to be keyed differently
   108  func MetaNamespaceKeyFunc(obj interface{}) (string, error) {
   109  	if key, ok := obj.(ExplicitKey); ok {
   110  		return string(key), nil
   111  	}
   112  	objName, err := ObjectToName(obj)
   113  	if err != nil {
   114  		return "", err
   115  	}
   116  	return objName.String(), nil
   117  }
   118  
   119  // ObjectToName returns the structured name for the given object,
   120  // if indeed it can be viewed as a metav1.Object.
   121  func ObjectToName(obj interface{}) (ObjectName, error) {
   122  	meta, err := meta.Accessor(obj)
   123  	if err != nil {
   124  		return ObjectName{}, fmt.Errorf("object has no meta: %v", err)
   125  	}
   126  	return MetaObjectToName(meta), nil
   127  }
   128  
   129  // MetaObjectToName returns the structured name for the given object
   130  func MetaObjectToName(obj metav1.Object) ObjectName {
   131  	if len(obj.GetNamespace()) > 0 {
   132  		return ObjectName{Namespace: obj.GetNamespace(), Name: obj.GetName()}
   133  	}
   134  	return ObjectName{Namespace: "", Name: obj.GetName()}
   135  }
   136  
   137  // SplitMetaNamespaceKey returns the namespace and name that
   138  // MetaNamespaceKeyFunc encoded into key.
   139  //
   140  // TODO: replace key-as-string with a key-as-struct so that this
   141  // packing/unpacking won't be necessary.
   142  func SplitMetaNamespaceKey(key string) (namespace, name string, err error) {
   143  	parts := strings.Split(key, "/")
   144  	switch len(parts) {
   145  	case 1:
   146  		// name only, no namespace
   147  		return "", parts[0], nil
   148  	case 2:
   149  		// namespace and name
   150  		return parts[0], parts[1], nil
   151  	}
   152  
   153  	return "", "", fmt.Errorf("unexpected key format: %q", key)
   154  }
   155  
   156  // `*cache` implements Indexer in terms of a ThreadSafeStore and an
   157  // associated KeyFunc.
   158  type cache struct {
   159  	// cacheStorage bears the burden of thread safety for the cache
   160  	cacheStorage ThreadSafeStore
   161  	// keyFunc is used to make the key for objects stored in and retrieved from items, and
   162  	// should be deterministic.
   163  	keyFunc KeyFunc
   164  }
   165  
   166  var _ Store = &cache{}
   167  
   168  // Add inserts an item into the cache.
   169  func (c *cache) Add(obj interface{}) error {
   170  	key, err := c.keyFunc(obj)
   171  	if err != nil {
   172  		return KeyError{obj, err}
   173  	}
   174  	c.cacheStorage.Add(key, obj)
   175  	return nil
   176  }
   177  
   178  // Update sets an item in the cache to its updated state.
   179  func (c *cache) Update(obj interface{}) error {
   180  	key, err := c.keyFunc(obj)
   181  	if err != nil {
   182  		return KeyError{obj, err}
   183  	}
   184  	c.cacheStorage.Update(key, obj)
   185  	return nil
   186  }
   187  
   188  // Delete removes an item from the cache.
   189  func (c *cache) Delete(obj interface{}) error {
   190  	key, err := c.keyFunc(obj)
   191  	if err != nil {
   192  		return KeyError{obj, err}
   193  	}
   194  	c.cacheStorage.Delete(key)
   195  	return nil
   196  }
   197  
   198  // List returns a list of all the items.
   199  // List is completely threadsafe as long as you treat all items as immutable.
   200  func (c *cache) List() []interface{} {
   201  	return c.cacheStorage.List()
   202  }
   203  
   204  // ListKeys returns a list of all the keys of the objects currently
   205  // in the cache.
   206  func (c *cache) ListKeys() []string {
   207  	return c.cacheStorage.ListKeys()
   208  }
   209  
   210  // GetIndexers returns the indexers of cache
   211  func (c *cache) GetIndexers() Indexers {
   212  	return c.cacheStorage.GetIndexers()
   213  }
   214  
   215  // Index returns a list of items that match on the index function
   216  // Index is thread-safe so long as you treat all items as immutable
   217  func (c *cache) Index(indexName string, obj interface{}) ([]interface{}, error) {
   218  	return c.cacheStorage.Index(indexName, obj)
   219  }
   220  
   221  // IndexKeys returns the storage keys of the stored objects whose set of
   222  // indexed values for the named index includes the given indexed value.
   223  // The returned keys are suitable to pass to GetByKey().
   224  func (c *cache) IndexKeys(indexName, indexedValue string) ([]string, error) {
   225  	return c.cacheStorage.IndexKeys(indexName, indexedValue)
   226  }
   227  
   228  // ListIndexFuncValues returns the list of generated values of an Index func
   229  func (c *cache) ListIndexFuncValues(indexName string) []string {
   230  	return c.cacheStorage.ListIndexFuncValues(indexName)
   231  }
   232  
   233  // ByIndex returns the stored objects whose set of indexed values
   234  // for the named index includes the given indexed value.
   235  func (c *cache) ByIndex(indexName, indexedValue string) ([]interface{}, error) {
   236  	return c.cacheStorage.ByIndex(indexName, indexedValue)
   237  }
   238  
   239  func (c *cache) AddIndexers(newIndexers Indexers) error {
   240  	return c.cacheStorage.AddIndexers(newIndexers)
   241  }
   242  
   243  // Get returns the requested item, or sets exists=false.
   244  // Get is completely threadsafe as long as you treat all items as immutable.
   245  func (c *cache) Get(obj interface{}) (item interface{}, exists bool, err error) {
   246  	key, err := c.keyFunc(obj)
   247  	if err != nil {
   248  		return nil, false, KeyError{obj, err}
   249  	}
   250  	return c.GetByKey(key)
   251  }
   252  
   253  // GetByKey returns the request item, or exists=false.
   254  // GetByKey is completely threadsafe as long as you treat all items as immutable.
   255  func (c *cache) GetByKey(key string) (item interface{}, exists bool, err error) {
   256  	item, exists = c.cacheStorage.Get(key)
   257  	return item, exists, nil
   258  }
   259  
   260  // Replace will delete the contents of 'c', using instead the given list.
   261  // 'c' takes ownership of the list, you should not reference the list again
   262  // after calling this function.
   263  func (c *cache) Replace(list []interface{}, resourceVersion string) error {
   264  	items := make(map[string]interface{}, len(list))
   265  	for _, item := range list {
   266  		key, err := c.keyFunc(item)
   267  		if err != nil {
   268  			return KeyError{item, err}
   269  		}
   270  		items[key] = item
   271  	}
   272  	c.cacheStorage.Replace(items, resourceVersion)
   273  	return nil
   274  }
   275  
   276  // Resync is meaningless for one of these
   277  func (c *cache) Resync() error {
   278  	return nil
   279  }
   280  
   281  // NewStore returns a Store implemented simply with a map and a lock.
   282  func NewStore(keyFunc KeyFunc) Store {
   283  	return &cache{
   284  		cacheStorage: NewThreadSafeStore(Indexers{}, Indices{}),
   285  		keyFunc:      keyFunc,
   286  	}
   287  }
   288  
   289  // NewIndexer returns an Indexer implemented simply with a map and a lock.
   290  func NewIndexer(keyFunc KeyFunc, indexers Indexers) Indexer {
   291  	return &cache{
   292  		cacheStorage: NewThreadSafeStore(indexers, Indices{}),
   293  		keyFunc:      keyFunc,
   294  	}
   295  }
   296  

View as plain text