1/*
2Copyright 2014 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package cache
18
19import (
20	"fmt"
21
22	"k8s.io/apimachinery/pkg/api/meta"
23	"k8s.io/apimachinery/pkg/util/sets"
24)
25
26// Indexer extends Store with multiple indices and restricts each
27// accumulator to simply hold the current object (and be empty after
28// Delete).
29//
30// There are three kinds of strings here:
31// 1. a storage key, as defined in the Store interface,
32// 2. a name of an index, and
33// 3. an "indexed value", which is produced by an IndexFunc and
34//    can be a field value or any other string computed from the object.
35type Indexer interface {
36	Store
37	// Index returns the stored objects whose set of indexed values
38	// intersects the set of indexed values of the given object, for
39	// the named index
40	Index(indexName string, obj interface{}) ([]interface{}, error)
41	// IndexKeys returns the storage keys of the stored objects whose
42	// set of indexed values for the named index includes the given
43	// indexed value
44	IndexKeys(indexName, indexedValue string) ([]string, error)
45	// ListIndexFuncValues returns all the indexed values of the given index
46	ListIndexFuncValues(indexName string) []string
47	// ByIndex returns the stored objects whose set of indexed values
48	// for the named index includes the given indexed value
49	ByIndex(indexName, indexedValue string) ([]interface{}, error)
50	// GetIndexer return the indexers
51	GetIndexers() Indexers
52
53	// AddIndexers adds more indexers to this store.  If you call this after you already have data
54	// in the store, the results are undefined.
55	AddIndexers(newIndexers Indexers) error
56}
57
58// IndexFunc knows how to compute the set of indexed values for an object.
59type IndexFunc func(obj interface{}) ([]string, error)
60
61// IndexFuncToKeyFuncAdapter adapts an indexFunc to a keyFunc.  This is only useful if your index function returns
62// unique values for every object.  This conversion can create errors when more than one key is found.  You
63// should prefer to make proper key and index functions.
64func IndexFuncToKeyFuncAdapter(indexFunc IndexFunc) KeyFunc {
65	return func(obj interface{}) (string, error) {
66		indexKeys, err := indexFunc(obj)
67		if err != nil {
68			return "", err
69		}
70		if len(indexKeys) > 1 {
71			return "", fmt.Errorf("too many keys: %v", indexKeys)
72		}
73		if len(indexKeys) == 0 {
74			return "", fmt.Errorf("unexpected empty indexKeys")
75		}
76		return indexKeys[0], nil
77	}
78}
79
80const (
81	// NamespaceIndex is the lookup name for the most comment index function, which is to index by the namespace field.
82	NamespaceIndex string = "namespace"
83)
84
85// MetaNamespaceIndexFunc is a default index function that indexes based on an object's namespace
86func MetaNamespaceIndexFunc(obj interface{}) ([]string, error) {
87	meta, err := meta.Accessor(obj)
88	if err != nil {
89		return []string{""}, fmt.Errorf("object has no meta: %v", err)
90	}
91	return []string{meta.GetNamespace()}, nil
92}
93
94// Index maps the indexed value to a set of keys in the store that match on that value
95type Index map[string]sets.String
96
97// Indexers maps a name to a IndexFunc
98type Indexers map[string]IndexFunc
99
100// Indices maps a name to an Index
101type Indices map[string]Index
102