diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_test.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_test.go index ed200166883..1ebf52e06cf 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_test.go @@ -513,7 +513,7 @@ type setupOptions struct { type setupOption func(*setupOptions) func withDefaults(options *setupOptions) { - prefix := "/pods" + prefix := "/pods/" options.resourcePrefix = prefix options.keyFunc = func(obj runtime.Object) (string, error) { return storage.NamespaceKeyFunc(prefix, obj) } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_whitebox_test.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_whitebox_test.go index 3c82d7dc291..a9d7bf8bd20 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_whitebox_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_whitebox_test.go @@ -64,7 +64,7 @@ import ( ) func newTestCacherWithoutSyncing(s storage.Interface, c clock.WithTicker) (*Cacher, storage.Versioner, error) { - prefix := "/pods" + prefix := "/pods/" config := Config{ Storage: s, Versioner: storage.APIObjectVersioner{}, diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/watch_cache_test.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/watch_cache_test.go index 520bdcdfd3d..1c090269c55 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/watch_cache_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/watch_cache_test.go @@ -71,7 +71,7 @@ func makeTestPodDetails(name string, resourceVersion uint64, nodeName string, la func makeTestStoreElement(pod *v1.Pod) *storeElement { return &storeElement{ - Key: "prefix/ns/" + pod.Name, + Key: "/prefix/ns/" + pod.Name, Object: pod, Labels: labels.Set(pod.Labels), Fields: fields.Set{"spec.nodeName": pod.Spec.NodeName}, @@ -116,7 +116,7 @@ func (w *testWatchCache) getCacheIntervalForEvents(resourceVersion uint64, opts // newTestWatchCache just adds a fake clock. func newTestWatchCache(capacity int, eventFreshDuration time.Duration, indexers *cache.Indexers) *testWatchCache { keyFunc := func(obj runtime.Object) (string, error) { - return storage.NamespaceKeyFunc("prefix", obj) + return storage.NamespaceKeyFunc("/prefix/", obj) } getAttrsFunc := func(obj runtime.Object) (labels.Set, fields.Set, error) { pod, ok := obj.(*v1.Pod) @@ -244,9 +244,9 @@ func TestWatchCacheBasic(t *testing.T) { store.Add(makeTestPod("pod3", 6)) { expected := map[string]storeElement{ - "prefix/ns/pod1": *makeTestStoreElement(makeTestPod("pod1", 4)), - "prefix/ns/pod2": *makeTestStoreElement(makeTestPod("pod2", 5)), - "prefix/ns/pod3": *makeTestStoreElement(makeTestPod("pod3", 6)), + "/prefix/ns/pod1": *makeTestStoreElement(makeTestPod("pod1", 4)), + "/prefix/ns/pod2": *makeTestStoreElement(makeTestPod("pod2", 5)), + "/prefix/ns/pod3": *makeTestStoreElement(makeTestPod("pod3", 6)), } items := make(map[string]storeElement) for _, item := range store.List() { @@ -265,8 +265,8 @@ func TestWatchCacheBasic(t *testing.T) { }, "8") { expected := map[string]storeElement{ - "prefix/ns/pod4": *makeTestStoreElement(makeTestPod("pod4", 7)), - "prefix/ns/pod5": *makeTestStoreElement(makeTestPod("pod5", 8)), + "/prefix/ns/pod4": *makeTestStoreElement(makeTestPod("pod4", 7)), + "/prefix/ns/pod5": *makeTestStoreElement(makeTestPod("pod5", 8)), } items := make(map[string]storeElement) for _, item := range store.List() { @@ -470,7 +470,7 @@ func TestWaitUntilFreshAndGetList(t *testing.T) { }() // list by empty MatchValues. - resp, indexUsed, err := store.WaitUntilFreshAndGetList(ctx, "prefix/", storage.ListOptions{ResourceVersion: "5", Recursive: true, Predicate: storage.Everything}) + resp, indexUsed, err := store.WaitUntilFreshAndGetList(ctx, "/prefix/", storage.ListOptions{ResourceVersion: "5", Recursive: true, Predicate: storage.Everything}) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -485,7 +485,7 @@ func TestWaitUntilFreshAndGetList(t *testing.T) { } // list by label index. - resp, indexUsed, err = store.WaitUntilFreshAndGetList(ctx, "prefix/", storage.ListOptions{ResourceVersion: "5", Recursive: true, Predicate: storage.SelectionPredicate{ + resp, indexUsed, err = store.WaitUntilFreshAndGetList(ctx, "/prefix/", storage.ListOptions{ResourceVersion: "5", Recursive: true, Predicate: storage.SelectionPredicate{ Label: labels.SelectorFromSet(map[string]string{ "label": "value1", }), @@ -508,7 +508,7 @@ func TestWaitUntilFreshAndGetList(t *testing.T) { } // list with spec.nodeName index. - resp, indexUsed, err = store.WaitUntilFreshAndGetList(ctx, "prefix/", storage.ListOptions{ResourceVersion: "5", Recursive: true, Predicate: storage.SelectionPredicate{ + resp, indexUsed, err = store.WaitUntilFreshAndGetList(ctx, "/prefix/", storage.ListOptions{ResourceVersion: "5", Recursive: true, Predicate: storage.SelectionPredicate{ Label: labels.SelectorFromSet(map[string]string{ "not-exist-label": "whatever", }), @@ -531,7 +531,7 @@ func TestWaitUntilFreshAndGetList(t *testing.T) { } // list with index not exists. - resp, indexUsed, err = store.WaitUntilFreshAndGetList(ctx, "prefix/", storage.ListOptions{ResourceVersion: "5", Recursive: true, Predicate: storage.SelectionPredicate{ + resp, indexUsed, err = store.WaitUntilFreshAndGetList(ctx, "/prefix/", storage.ListOptions{ResourceVersion: "5", Recursive: true, Predicate: storage.SelectionPredicate{ Label: labels.SelectorFromSet(map[string]string{ "not-exist-label": "whatever", }), @@ -565,7 +565,7 @@ func TestWaitUntilFreshAndListFromCache(t *testing.T) { }() // list from future revision. Requires watch cache to request bookmark to get it. - resp, indexUsed, err := store.WaitUntilFreshAndGetList(ctx, "prefix/", storage.ListOptions{ResourceVersion: "3", Recursive: true, Predicate: storage.Everything}) + resp, indexUsed, err := store.WaitUntilFreshAndGetList(ctx, "/prefix/", storage.ListOptions{ResourceVersion: "3", Recursive: true, Predicate: storage.Everything}) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -591,7 +591,7 @@ func TestWaitUntilFreshAndGet(t *testing.T) { store.Add(makeTestPod("bar", 5)) }() - obj, exists, resourceVersion, err := store.WaitUntilFreshAndGet(ctx, 5, "prefix/ns/bar") + obj, exists, resourceVersion, err := store.WaitUntilFreshAndGet(ctx, 5, "/prefix/ns/bar") if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/util.go b/staging/src/k8s.io/apiserver/pkg/storage/util.go index bb231df3038..3ca9acf3bd2 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/util.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/util.go @@ -18,6 +18,7 @@ package storage import ( "fmt" + "strings" "sync/atomic" "k8s.io/apimachinery/pkg/api/meta" @@ -37,6 +38,9 @@ func SimpleUpdate(fn SimpleUpdateFunc) UpdateFunc { } func NamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) { + if !strings.HasSuffix(prefix, "/") { + return "", fmt.Errorf("prefix should have '/' suffix") + } meta, err := meta.Accessor(obj) if err != nil { return "", err @@ -45,10 +49,13 @@ func NamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) { if msgs := path.IsValidPathSegmentName(name); len(msgs) != 0 { return "", fmt.Errorf("invalid name: %v", msgs) } - return prefix + "/" + meta.GetNamespace() + "/" + name, nil + return prefix + meta.GetNamespace() + "/" + name, nil } func NoNamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) { + if !strings.HasSuffix(prefix, "/") { + return "", fmt.Errorf("prefix should have '/' suffix") + } meta, err := meta.Accessor(obj) if err != nil { return "", err @@ -57,7 +64,7 @@ func NoNamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) { if msgs := path.IsValidPathSegmentName(name); len(msgs) != 0 { return "", fmt.Errorf("invalid name: %v", msgs) } - return prefix + "/" + name, nil + return prefix + name, nil } // HighWaterMark is a thread-safe object for tracking the maximum value seen