diff --git a/pkg/client/cache/index.go b/pkg/client/cache/index.go index 7d5638cae87..82c7a7c8188 100644 --- a/pkg/client/cache/index.go +++ b/pkg/client/cache/index.go @@ -28,6 +28,8 @@ type Indexer interface { Store // Retrieve list of objects that match on the named indexing function Index(indexName string, obj interface{}) ([]interface{}, error) + // ListIndexFuncValues returns the list of generated values of an Index func + ListIndexFuncValues(indexName string) []string } // IndexFunc knows how to provide an indexed value for an object. diff --git a/pkg/client/cache/index_test.go b/pkg/client/cache/index_test.go new file mode 100644 index 00000000000..12985a82640 --- /dev/null +++ b/pkg/client/cache/index_test.go @@ -0,0 +1,50 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cache + +import ( + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "testing" +) + +func testIndexFunc(obj interface{}) (string, error) { + pod := obj.(*api.Pod) + return pod.Labels["foo"], nil +} + +func TestGetIndexFuncValues(t *testing.T) { + index := NewIndexer(MetaNamespaceKeyFunc, Indexers{"testmodes": testIndexFunc}) + + pod1 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "one", Labels: map[string]string{"foo": "bar"}}} + pod2 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "two", Labels: map[string]string{"foo": "bar"}}} + pod3 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "tre", Labels: map[string]string{"foo": "biz"}}} + + index.Add(pod1) + index.Add(pod2) + index.Add(pod3) + + keys := index.ListIndexFuncValues("testmodes") + if len(keys) != 2 { + t.Errorf("Expected 2 keys but got %v", len(keys)) + } + + for _, key := range keys { + if key != "bar" && key != "biz" { + t.Errorf("Expected only 'bar' or 'biz' but got %s", key) + } + } +} diff --git a/pkg/client/cache/store.go b/pkg/client/cache/store.go index 9b18293fd4d..1f103b61c3d 100644 --- a/pkg/client/cache/store.go +++ b/pkg/client/cache/store.go @@ -164,6 +164,11 @@ func (c *cache) Index(indexName string, obj interface{}) ([]interface{}, error) return c.cacheStorage.Index(indexName, obj) } +// ListIndexFuncValues returns the list of generated values of an Index func +func (c *cache) ListIndexFuncValues(indexName string) []string { + return c.cacheStorage.ListIndexFuncValues(indexName) +} + // Get returns the requested item, or sets exists=false. // Get is completely threadsafe as long as you treat all items as immutable. func (c *cache) Get(obj interface{}) (item interface{}, exists bool, err error) { diff --git a/pkg/client/cache/thread_safe_store.go b/pkg/client/cache/thread_safe_store.go index 7700e049ba0..81495832e8f 100644 --- a/pkg/client/cache/thread_safe_store.go +++ b/pkg/client/cache/thread_safe_store.go @@ -43,6 +43,7 @@ type ThreadSafeStore interface { ListKeys() []string Replace(map[string]interface{}) Index(indexName string, obj interface{}) ([]interface{}, error) + ListIndexFuncValues(name string) []string } // threadSafeMap implements ThreadSafeStore @@ -146,6 +147,15 @@ func (c *threadSafeMap) Index(indexName string, obj interface{}) ([]interface{}, return list, nil } +func (c *threadSafeMap) ListIndexFuncValues(indexName string) []string { + index := c.indices[indexName] + names := make([]string, 0, len(index)) + for key := range index { + names = append(names, key) + } + return names +} + // updateIndices modifies the objects location in the managed indexes, if this is an update, you must provide an oldObj // updateIndices must be called from a function that already has a lock on the cache func (c *threadSafeMap) updateIndices(oldObj interface{}, newObj interface{}, key string) error {