From 3a51260ef9370a7edc36004c2b269121b6c059ef Mon Sep 17 00:00:00 2001 From: Todd Treece <360020+toddtreece@users.noreply.github.com> Date: Fri, 12 Jul 2024 08:54:00 -0400 Subject: [PATCH] K8s: Add file store tests (#90151) --- pkg/apiserver/storage/file/file.go | 199 ++++++------- pkg/apiserver/storage/file/file_test.go | 279 +++++++++++++++++++ pkg/apiserver/storage/file/util.go | 8 + pkg/apiserver/storage/file/watcher_test.go | 14 +- pkg/apiserver/storage/testing/store_tests.go | 144 +++++----- 5 files changed, 454 insertions(+), 190 deletions(-) create mode 100644 pkg/apiserver/storage/file/file_test.go diff --git a/pkg/apiserver/storage/file/file.go b/pkg/apiserver/storage/file/file.go index 8bd936a671a..e4526707922 100644 --- a/pkg/apiserver/storage/file/file.go +++ b/pkg/apiserver/storage/file/file.go @@ -15,9 +15,9 @@ import ( "sync" "time" - "github.com/bwmarrin/snowflake" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" + metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -35,10 +35,6 @@ const MaxUpdateAttempts = 30 var _ storage.Interface = (*Storage)(nil) -// Replace with: https://github.com/kubernetes/kubernetes/blob/v1.29.0-alpha.3/staging/src/k8s.io/apiserver/pkg/storage/errors.go#L28 -// When we upgrade to 1.29 -var errResourceVersionSetOnCreate = errors.New("resourceVersion should not be set on objects to be created") - // Storage implements storage.Interface and storage resources as JSON files on disk. type Storage struct { root string @@ -52,7 +48,6 @@ type Storage struct { trigger storage.IndexerFuncs indexers *cache.Indexers - rvGenerationNode *snowflake.Node // rvMutex provides synchronization between Get and GetList+Watch+CUD methods // with access to resource version generation for the latter group rvMutex sync.RWMutex @@ -84,11 +79,6 @@ func NewStorage( return nil, func() {}, fmt.Errorf("could not establish a writable directory at path=%s", root) } - rvGenerationNode, err := snowflake.NewNode(1) - if err != nil { - return nil, nil, err - } - s := &Storage{ root: root, resourcePrefix: resourcePrefix, @@ -101,14 +91,13 @@ func NewStorage( trigger: trigger, indexers: indexers, - rvGenerationNode: rvGenerationNode, - watchSet: NewWatchSet(), + watchSet: NewWatchSet(), versioner: &storage.APIObjectVersioner{}, } // Initialize the RV stored in storage - s.getNewResourceVersion() + s.getCurrentResourceVersion() return s, func() { s.watchSet.cleanupWatchers() @@ -116,12 +105,36 @@ func NewStorage( } func (s *Storage) getNewResourceVersion() uint64 { - snowflakeNumber := s.rvGenerationNode.Generate().Int64() - s.currentRV = uint64(snowflakeNumber) + s.currentRV += 1 return s.currentRV } func (s *Storage) getCurrentResourceVersion() uint64 { + if s.currentRV != 0 { + return s.currentRV + } + + objs, err := readDirRecursive(s.codec, s.root, s.newFunc) + if err != nil { + s.currentRV = 1 + return s.currentRV + } + + for _, obj := range objs { + currentVersion, err := s.versioner.ObjectResourceVersion(obj) + if err != nil && s.currentRV == 0 { + s.currentRV = 1 + continue + } + if currentVersion > s.currentRV { + s.currentRV = currentVersion + } + } + + if s.currentRV == 0 { + s.currentRV = 1 + } + return s.currentRV } @@ -154,7 +167,7 @@ func (s *Storage) Create(ctx context.Context, key string, obj runtime.Object, ou } metaObj.SetSelfLink("") if metaObj.GetResourceVersion() != "" { - return errResourceVersionSetOnCreate + return storage.ErrResourceVersionSetOnCreate } if err := s.versioner.UpdateObject(obj, generatedRV); err != nil { @@ -197,76 +210,40 @@ func (s *Storage) Delete( out runtime.Object, preconditions *storage.Preconditions, validateDeletion storage.ValidateObjectFunc, - cachedExistingObject runtime.Object, + _ runtime.Object, ) error { - // TODO: is it gonna be contentious - // Either way, this should have max attempts logic s.rvMutex.Lock() defer s.rvMutex.Unlock() fpath := s.filePath(key) - var currentState runtime.Object - var stateIsCurrent bool - if cachedExistingObject != nil { - currentState = cachedExistingObject - } else { - getOptions := storage.GetOptions{} - if preconditions != nil && preconditions.ResourceVersion != nil { - getOptions.ResourceVersion = *preconditions.ResourceVersion - } - if err := s.Get(ctx, key, getOptions, currentState); err == nil { - stateIsCurrent = true + if err := s.Get(ctx, key, storage.GetOptions{}, out); err != nil { + return err + } + + if preconditions != nil { + if err := preconditions.Check(key, out); err != nil { + return err } } - for { - if preconditions != nil { - if err := preconditions.Check(key, out); err != nil { - if stateIsCurrent { - return err - } - - // If the state is not current, we need to re-read the state and try again. - if err := s.Get(ctx, key, storage.GetOptions{}, currentState); err != nil { - return err - } - stateIsCurrent = true - continue - } - } - - if err := validateDeletion(ctx, out); err != nil { - if stateIsCurrent { - return err - } - - // If the state is not current, we need to re-read the state and try again. - if err := s.Get(ctx, key, storage.GetOptions{}, currentState); err == nil { - stateIsCurrent = true - } - continue - } - - if err := s.Get(ctx, key, storage.GetOptions{}, out); err != nil { - return err - } - - generatedRV := s.getNewResourceVersion() - if err := s.versioner.UpdateObject(out, generatedRV); err != nil { - return err - } - - if err := deleteFile(fpath); err != nil { - return err - } - - s.watchSet.notifyWatchers(watch.Event{ - Object: out.DeepCopyObject(), - Type: watch.Deleted, - }, nil) - - return nil + generatedRV := s.getNewResourceVersion() + if err := s.versioner.UpdateObject(out, generatedRV); err != nil { + return err } + + if err := validateDeletion(ctx, out); err != nil { + return err + } + + if err := deleteFile(fpath); err != nil { + return err + } + + s.watchSet.notifyWatchers(watch.Event{ + Object: out.DeepCopyObject(), + Type: watch.Deleted, + }, nil) + return nil } // Watch begins watching the specified key. Events are decoded into API objects, @@ -338,8 +315,7 @@ func (s *Storage) Watch(ctx context.Context, key string, opts storage.ListOption } if p.AllowWatchBookmarks && len(initEvents) > 0 { - lastInitEvent := initEvents[len(initEvents)-1] - lastItemRV, err := s.versioner.ObjectResourceVersion(lastInitEvent.Object) + listRV, err := s.versioner.ParseResourceVersion(listAccessor.GetResourceVersion()) if err != nil { return nil, fmt.Errorf("could not get last init event's revision for bookmark: %v", err) } @@ -349,7 +325,7 @@ func (s *Storage) Watch(ctx context.Context, key string, opts storage.ListOption Object: s.newFunc(), } - if err := s.versioner.UpdateObject(bookmarkEvent.Object, lastItemRV); err != nil { + if err := s.versioner.UpdateObject(bookmarkEvent.Object, listRV); err != nil { return nil, err } @@ -398,7 +374,7 @@ func (s *Storage) Get(ctx context.Context, key string, opts storage.GetOptions, } obj, err := readFile(s.codec, fpath, func() runtime.Object { - return objPtr + return s.newFunc() }) if err != nil { if opts.IgnoreNotFound { @@ -407,12 +383,11 @@ func (s *Storage) Get(ctx context.Context, key string, opts storage.GetOptions, return storage.NewKeyNotFoundError(key, int64(rv)) } - currentVersion, err := s.versioner.ObjectResourceVersion(obj) - if err != nil { + if err := copyModifiedObjectToDestination(obj, objPtr); err != nil { return err } - if err = s.validateMinimumResourceVersion(opts.ResourceVersion, currentVersion); err != nil { + if err = s.validateMinimumResourceVersion(opts.ResourceVersion, s.getCurrentResourceVersion()); err != nil { return err } @@ -426,18 +401,15 @@ func (s *Storage) Get(ctx context.Context, key string, opts storage.GetOptions, // The returned contents may be delayed, but it is guaranteed that they will // match 'opts.ResourceVersion' according 'opts.ResourceVersionMatch'. func (s *Storage) GetList(ctx context.Context, key string, opts storage.ListOptions, listObj runtime.Object) error { - remainingItems := int64(0) - - resourceVersionInt, err := s.versioner.ParseResourceVersion(opts.ResourceVersion) - if err != nil { - return err - } + resourceVersionInt := uint64(0) // read state protected by mutex objs, err := func() ([]runtime.Object, error) { s.rvMutex.Lock() defer s.rvMutex.Unlock() + resourceVersionInt = s.getCurrentResourceVersion() + var fpath string dirpath := s.dirPath(key) // Since it's a get, check if the dir exists and return early as needed @@ -473,6 +445,10 @@ func (s *Storage) GetList(ctx context.Context, key string, opts storage.ListOpti return err } + if err := s.validateMinimumResourceVersion(opts.ResourceVersion, resourceVersionInt); err != nil { + return err + } + listPtr, err := meta.GetItemsPtr(listObj) if err != nil { return err @@ -482,20 +458,22 @@ func (s *Storage) GetList(ctx context.Context, key string, opts storage.ListOpti return err } - for _, obj := range objs { - currentVersion, err := s.versioner.ObjectResourceVersion(obj) - if err != nil { - return err - } + if v.IsNil() { + v.Set(reflect.MakeSlice(v.Type(), 0, 0)) + } - if opts.SendInitialEvents == nil || (opts.SendInitialEvents != nil && !*opts.SendInitialEvents) { - // Apply the minimum resource version validation when we are not being called as part of Watch - // SendInitialEvents flow - // reason: the resource version of currently returned init items will always be < list RV - // they are being generated for, unless of course, the requestedRV == "0"/"" - if err := s.validateMinimumResourceVersion(opts.ResourceVersion, currentVersion); err != nil { - // Below log left for debug. It's usually not an error condition - // klog.Infof("failed to assert minimum resource version constraint against list version") + remainingItems := (*int64)(nil) + for i, obj := range objs { + if opts.ResourceVersionMatch == metaV1.ResourceVersionMatchExact { + currentVersion, err := s.versioner.ObjectResourceVersion(obj) + if err != nil { + return err + } + expectedRV, err := s.versioner.ParseResourceVersion(opts.ResourceVersion) + if err != nil { + return err + } + if currentVersion != expectedRV { continue } } @@ -504,13 +482,15 @@ func (s *Storage) GetList(ctx context.Context, key string, opts storage.ListOpti if err == nil && ok { v.Set(reflect.Append(v, reflect.ValueOf(obj).Elem())) } + + if int64(v.Len()) >= opts.Predicate.Limit && opts.Predicate.Limit > 0 { + remaining := int64(len(objs) - i - 1) + remainingItems = &remaining + break + } } - if resourceVersionInt == 0 { - resourceVersionInt = s.getNewResourceVersion() - } - - if err := s.versioner.UpdateList(listObj, resourceVersionInt, "", &remainingItems); err != nil { + if err := s.versioner.UpdateList(listObj, resourceVersionInt, "", remainingItems); err != nil { return err } @@ -663,6 +643,7 @@ func (s *Storage) validateMinimumResourceVersion(minimumResourceVersion string, if err != nil { return apierrors.NewBadRequest(fmt.Sprintf("invalid resource version: %v", err)) } + // Enforce the storage.Interface guarantee that the resource version of the returned data // "will be at least 'resourceVersion'". if minimumRV > actualRevision { diff --git a/pkg/apiserver/storage/file/file_test.go b/pkg/apiserver/storage/file/file_test.go new file mode 100644 index 00000000000..8204fea0b1d --- /dev/null +++ b/pkg/apiserver/storage/file/file_test.go @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: AGPL-3.0-only +// Provenance-includes-location: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_test.go +// Provenance-includes-license: Apache-2.0 +// Provenance-includes-copyright: The Kubernetes Authors. + +package file + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apiserver/pkg/apis/example" + examplev1 "k8s.io/apiserver/pkg/apis/example/v1" + "k8s.io/apiserver/pkg/storage" + + storagetesting "github.com/grafana/grafana/pkg/apiserver/storage/testing" +) + +func init() { + metav1.AddToGroupVersion(scheme, metav1.SchemeGroupVersion) + utilruntime.Must(example.AddToScheme(scheme)) + utilruntime.Must(examplev1.AddToScheme(scheme)) +} + +// GetPodAttrs returns labels and fields of a given object for filtering purposes. +func GetPodAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { + pod, ok := obj.(*example.Pod) + if !ok { + return nil, nil, fmt.Errorf("not a pod") + } + return labels.Set(pod.ObjectMeta.Labels), PodToSelectableFields(pod), nil +} + +// PodToSelectableFields returns a field set that represents the object +// TODO: fields are not labels, and the validation rules for them do not apply. +func PodToSelectableFields(pod *example.Pod) fields.Set { + // The purpose of allocation with a given number of elements is to reduce + // amount of allocations needed to create the fields.Set. If you add any + // field here or the number of object-meta related fields changes, this should + // be adjusted. + podSpecificFieldsSet := make(fields.Set, 5) + podSpecificFieldsSet["spec.nodeName"] = pod.Spec.NodeName + podSpecificFieldsSet["spec.restartPolicy"] = string(pod.Spec.RestartPolicy) + podSpecificFieldsSet["status.phase"] = string(pod.Status.Phase) + return AddObjectMetaFieldsSet(podSpecificFieldsSet, &pod.ObjectMeta, true) +} + +func AddObjectMetaFieldsSet(source fields.Set, objectMeta *metav1.ObjectMeta, hasNamespaceField bool) fields.Set { + source["metadata.name"] = objectMeta.Name + if hasNamespaceField { + source["metadata.namespace"] = objectMeta.Namespace + } + return source +} + +func checkStorageInvariants(s storage.Interface) storagetesting.KeyValidation { + return func(ctx context.Context, t *testing.T, key string) { + obj := &example.Pod{} + err := s.Get(ctx, key, storage.GetOptions{}, obj) + if err != nil { + t.Fatalf("Get failed: %v", err) + } + } +} + +func TestCreate(t *testing.T) { + ctx, store, destroyFunc, err := testSetup(t) + defer destroyFunc() + assert.NoError(t, err) + storagetesting.RunTestCreate(ctx, t, store, checkStorageInvariants(store)) +} + +func TestCreateWithTTL(t *testing.T) { + ctx, store, destroyFunc, err := testSetup(t) + defer destroyFunc() + assert.NoError(t, err) + storagetesting.RunTestCreateWithTTL(ctx, t, store) +} + +func TestCreateWithKeyExist(t *testing.T) { + ctx, store, destroyFunc, err := testSetup(t) + defer destroyFunc() + assert.NoError(t, err) + storagetesting.RunTestCreateWithKeyExist(ctx, t, store) +} + +func TestGet(t *testing.T) { + ctx, store, destroyFunc, err := testSetup(t) + defer destroyFunc() + assert.NoError(t, err) + storagetesting.RunTestGet(ctx, t, store) +} + +func TestUnconditionalDelete(t *testing.T) { + ctx, store, destroyFunc, err := testSetup(t) + defer destroyFunc() + assert.NoError(t, err) + storagetesting.RunTestUnconditionalDelete(ctx, t, store) +} + +func TestConditionalDelete(t *testing.T) { + ctx, store, destroyFunc, err := testSetup(t) + defer destroyFunc() + assert.NoError(t, err) + storagetesting.RunTestConditionalDelete(ctx, t, store) +} + +func TestDeleteWithSuggestion(t *testing.T) { + ctx, store, destroyFunc, err := testSetup(t) + defer destroyFunc() + assert.NoError(t, err) + storagetesting.RunTestDeleteWithSuggestion(ctx, t, store) +} + +//func TestDeleteWithSuggestionAndConflict(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestDeleteWithSuggestionAndConflict(ctx, t, store) +//} + +// TODO: this test relies on update +//func TestDeleteWithSuggestionOfDeletedObject(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestDeleteWithSuggestionOfDeletedObject(ctx, t, store) +//} + +//func TestValidateDeletionWithSuggestion(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestValidateDeletionWithSuggestion(ctx, t, store) +//} +// +//func TestPreconditionalDeleteWithSuggestion(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestPreconditionalDeleteWithSuggestion(ctx, t, store) +//} + +//func TestList(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestList(ctx, t, store, func(ctx context.Context, t *testing.T, rv string) { +// +// }, true) +//} + +//func compact(store *Storage) storagetesting.Compaction { +// return func(ctx context.Context, t *testing.T, resourceVersion string) { +// // tests expect that the resource version is incremented after compaction: +// // https://github.com/kubernetes/apiserver/blob/4f7f407e71725f4056328bbeb6d6139843716ca6/pkg/storage/etcd3/compact.go#L137 +// _ = store.getNewResourceVersion() +// } +//} + +//func TestGetListNonRecursive(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestGetListNonRecursive(ctx, t, compact(store.(*Storage)), store) +//} + +//func checkStorageCalls(t *testing.T, pageSize, estimatedProcessedObjects uint64) { +// if reads := getReadsAndReset(); reads != estimatedProcessedObjects { +// t.Errorf("unexpected reads: %d, expected: %d", reads, estimatedProcessedObjects) +// } +// estimatedGetCalls := uint64(1) +// if pageSize != 0 { +// // We expect that kube-apiserver will be increasing page sizes +// // if not full pages are received, so we should see significantly less +// // than 1000 pages (which would be result of talking to etcd with page size +// // copied from pred.Limit). +// // The expected number of calls is n+1 where n is the smallest n so that: +// // pageSize + pageSize * 2 + pageSize * 4 + ... + pageSize * 2^n >= podCount. +// // For pageSize = 1, podCount = 1000, we get n+1 = 10, 2 ^ 10 = 1024. +// currLimit := pageSize +// for sum := uint64(1); sum < estimatedProcessedObjects; { +// currLimit *= 2 +// if currLimit > 10000 { +// currLimit = 10000 +// } +// sum += currLimit +// estimatedGetCalls++ +// } +// } +// if reads := getReadsAndReset(); reads != estimatedGetCalls { +// t.Errorf("unexpected reads: %d, expected: %d", reads, estimatedProcessedObjects) +// } +//} + +//func TestListContinuation(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestListContinuation(ctx, t, store, checkStorageCalls) +//} +// +//func TestListPaginationRareObject(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestListPaginationRareObject(ctx, t, store, checkStorageCalls) +//} +// +//func TestListContinuationWithFilter(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestListContinuationWithFilter(ctx, t, store, checkStorageCalls) +//} +// +//func TestListInconsistentContinuation(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestListInconsistentContinuation(ctx, t, store, compact(store.(*Storage))) +//} +// +//func TestConsistentList(t *testing.T) { +// // TODO(#109831): Enable use of this test and run it. +//} +// +//func TestGuaranteedUpdate(t *testing.T) { +// // ctx, store, destroyFunc, err := testSetup(t) +// // defer destroyFunc() +// // assert.NoError(t, err) +// // storagetesting.RunTestGuaranteedUpdate(ctx, t, store, nil) +//} +// +//func TestGuaranteedUpdateWithTTL(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestGuaranteedUpdateWithTTL(ctx, t, store) +//} +// +//func TestGuaranteedUpdateChecksStoredData(t *testing.T) { +// // ctx, store, destroyFunc, err := testSetup(t) +// // defer destroyFunc() +// // assert.NoError(t, err) +// // storagetesting.RunTestGuaranteedUpdateChecksStoredData(ctx, t, store) +//} +// +//func TestGuaranteedUpdateWithConflict(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestGuaranteedUpdateWithConflict(ctx, t, store) +//} +// +//func TestGuaranteedUpdateWithSuggestionAndConflict(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestGuaranteedUpdateWithSuggestionAndConflict(ctx, t, store) +//} + +func TestTransformationFailure(t *testing.T) { + // TODO(#109831): Enable use of this test and run it. +} + +//func TestCount(t *testing.T) { +// ctx, store, destroyFunc, err := testSetup(t) +// defer destroyFunc() +// assert.NoError(t, err) +// storagetesting.RunTestCount(ctx, t, store) +//} diff --git a/pkg/apiserver/storage/file/util.go b/pkg/apiserver/storage/file/util.go index 67cd5452bca..1ce9bf18dbe 100644 --- a/pkg/apiserver/storage/file/util.go +++ b/pkg/apiserver/storage/file/util.go @@ -11,6 +11,7 @@ import ( "os" "path/filepath" "strings" + "sync/atomic" "k8s.io/apimachinery/pkg/runtime" ) @@ -37,7 +38,14 @@ func writeFile(codec runtime.Codec, path string, obj runtime.Object) error { return os.WriteFile(path, buf.Bytes(), 0600) } +var fileReadCount uint64 = 0 + +//func getReadsAndReset() uint64 { +//return atomic.SwapUint64(&fileReadCount, 0) +//} + func readFile(codec runtime.Codec, path string, newFunc func() runtime.Object) (runtime.Object, error) { + atomic.AddUint64(&fileReadCount, 1) content, err := os.ReadFile(filepath.Clean(path)) if err != nil { return nil, err diff --git a/pkg/apiserver/storage/file/watcher_test.go b/pkg/apiserver/storage/file/watcher_test.go index 2eada00d284..8651bc24244 100644 --- a/pkg/apiserver/storage/file/watcher_test.go +++ b/pkg/apiserver/storage/file/watcher_test.go @@ -134,7 +134,7 @@ func TestWatchFromZero(t *testing.T) { // TestWatchFromNonZero tests that // - watch from non-0 should just watch changes after given version -func TestWatchFromNoneZero(t *testing.T) { +func TestWatchFromNonZero(t *testing.T) { ctx, store, destroyFunc, err := testSetup(t) defer destroyFunc() assert.NoError(t, err) @@ -148,10 +148,12 @@ func TestDelayedWatchDelivery(t *testing.T) { storagetesting.RunTestDelayedWatchDelivery(ctx, t, store) } -/* func TestWatchError(t *testing.T) { +/* +func TestWatchError(t *testing.T) { ctx, store, _ := testSetup(t) storagetesting.RunTestWatchError(ctx, t, &storeWithPrefixTransformer{store}) -} */ +} +*/ func TestWatchContextCancel(t *testing.T) { ctx, store, destroyFunc, err := testSetup(t) @@ -213,18 +215,12 @@ func TestEtcdWatchSemantics(t *testing.T) { storagetesting.RunWatchSemantics(ctx, t, store) } -// TODO: determine if this test case is useful to pass -// If we simply generate Snowflakes for List RVs (when none is passed in) as opposed to maxRV calculation, it makes -// our watch implementation and comparing items against the requested RV much more reliable. -// There is no guarantee that maxRV+1 won't end up being a future item's RV. -/* func TestEtcdWatchSemanticInitialEventsExtended(t *testing.T) { ctx, store, destroyFunc, err := testSetup(t) defer destroyFunc() assert.NoError(t, err) storagetesting.RunWatchSemanticInitialEventsExtended(ctx, t, store) } -*/ func newPod() runtime.Object { return &example.Pod{} diff --git a/pkg/apiserver/storage/testing/store_tests.go b/pkg/apiserver/storage/testing/store_tests.go index 1025c3781dd..6e0495b892a 100644 --- a/pkg/apiserver/storage/testing/store_tests.go +++ b/pkg/apiserver/storage/testing/store_tests.go @@ -658,14 +658,14 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }{ { name: "rejects invalid resource version", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.Everything, rv: "abc", expectError: true, }, { name: "rejects resource version and continue token", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.Everything(), @@ -677,26 +677,26 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "rejects resource version set too high", - prefix: "/pods", + prefix: KeyFunc("", ""), rv: strconv.FormatInt(math.MaxInt64, 10), expectRVTooLarge: true, }, { name: "test List on existing key", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.Everything, expectedOut: []example.Pod{*preset[0]}, }, { name: "test List on existing key with resource version set to 0", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.Everything, expectedAlternatives: [][]example.Pod{{}, {*preset[0]}}, rv: "0", }, { name: "test List on existing key with resource version set before first write, match=Exact", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.Everything, expectedOut: []example.Pod{}, rv: initialRV, @@ -705,7 +705,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List on existing key with resource version set to 0, match=NotOlderThan", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.Everything, expectedAlternatives: [][]example.Pod{{}, {*preset[0]}}, rv: "0", @@ -713,7 +713,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List on existing key with resource version set to 0, match=Invalid", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.Everything, rv: "0", rvMatch: "Invalid", @@ -721,7 +721,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List on existing key with resource version set before first write, match=NotOlderThan", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.Everything, expectedAlternatives: [][]example.Pod{{}, {*preset[0]}}, rv: initialRV, @@ -729,7 +729,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List on existing key with resource version set before first write, match=Invalid", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.Everything, rv: initialRV, rvMatch: "Invalid", @@ -737,14 +737,14 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List on existing key with resource version set to current resource version", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.Everything, expectedOut: []example.Pod{*preset[0]}, rv: list.ResourceVersion, }, { name: "test List on existing key with resource version set to current resource version, match=Exact", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.Everything, expectedOut: []example.Pod{*preset[0]}, rv: list.ResourceVersion, @@ -753,7 +753,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List on existing key with resource version set to current resource version, match=NotOlderThan", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.Everything, expectedOut: []example.Pod{*preset[0]}, rv: list.ResourceVersion, @@ -761,13 +761,13 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List on non-existing key", - prefix: "/pods/non-existing/", + prefix: KeyFunc("non-existing", ""), pred: storage.Everything, expectedOut: []example.Pod{}, }, { name: "test List with pod name matching", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.ParseSelectorOrDie("metadata.name!=bar"), @@ -776,7 +776,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with pod name matching with resource version set to current resource version, match=NotOlderThan", - prefix: "/pods/first/", + prefix: KeyFunc("first", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.ParseSelectorOrDie("metadata.name!=bar"), @@ -787,7 +787,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with limit", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.Everything(), @@ -799,7 +799,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with limit at current resource version", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.Everything(), @@ -813,7 +813,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with limit at current resource version and match=Exact", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.Everything(), @@ -828,7 +828,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with limit at current resource version and match=NotOlderThan", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.Everything(), @@ -843,7 +843,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with limit at resource version 0", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.Everything(), @@ -862,7 +862,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with limit at resource version 0 match=NotOlderThan", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.Everything(), @@ -882,7 +882,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with limit at resource version before first write and match=Exact", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.Everything(), @@ -896,7 +896,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with pregenerated continue token", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.Everything(), @@ -907,7 +907,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "ignores resource version 0 for List with pregenerated continue token", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.Everything(), @@ -919,13 +919,13 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with multiple levels of directories and expect flattened result", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.Everything, expectedOut: []example.Pod{*preset[1], *preset[2]}, }, { name: "test List with multiple levels of directories and expect flattened result with current resource version and match=NotOlderThan", - prefix: "/pods/second/", + prefix: KeyFunc("second", ""), pred: storage.Everything, rv: list.ResourceVersion, rvMatch: metav1.ResourceVersionMatchNotOlderThan, @@ -933,7 +933,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with filter returning only one item, ensure only a single page returned", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "barfoo"), Label: labels.Everything(), @@ -944,7 +944,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with filter returning only one item, ensure only a single page returned with current resource version and match=NotOlderThan", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "barfoo"), Label: labels.Everything(), @@ -957,7 +957,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with filter returning only one item, covers the entire list", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "barfoo"), Label: labels.Everything(), @@ -968,7 +968,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with filter returning only one item, covers the entire list with current resource version and match=NotOlderThan", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "barfoo"), Label: labels.Everything(), @@ -981,7 +981,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with filter returning only one item, covers the entire list, with resource version 0", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "barfoo"), Label: labels.Everything(), @@ -993,7 +993,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with filter returning two items, more pages possible", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "bar"), Label: labels.Everything(), @@ -1004,7 +1004,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test List with filter returning two items, more pages possible with current resource version and match=NotOlderThan", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "bar"), Label: labels.Everything(), @@ -1017,7 +1017,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "filter returns two items split across multiple pages", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "foo"), Label: labels.Everything(), @@ -1027,7 +1027,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "filter returns two items split across multiple pages with current resource version and match=NotOlderThan", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "foo"), Label: labels.Everything(), @@ -1039,7 +1039,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "filter returns one item for last page, ends on last item, not full", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "foo"), Label: labels.Everything(), @@ -1050,7 +1050,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "filter returns one item for last page, starts on last item, full", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "foo"), Label: labels.Everything(), @@ -1061,7 +1061,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "filter returns one item for last page, starts on last item, partial page", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "foo"), Label: labels.Everything(), @@ -1072,7 +1072,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "filter returns two items, page size equal to total list size", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "foo"), Label: labels.Everything(), @@ -1082,7 +1082,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "filter returns two items, page size equal to total list size with current resource version and match=NotOlderThan", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "foo"), Label: labels.Everything(), @@ -1094,7 +1094,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "filter returns one item, page size equal to total list size", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "barfoo"), Label: labels.Everything(), @@ -1104,7 +1104,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "filter returns one item, page size equal to total list size with current resource version and match=NotOlderThan", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "barfoo"), Label: labels.Everything(), @@ -1116,13 +1116,13 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "list all items", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.Everything, expectedOut: []example.Pod{*preset[0], *preset[1], *preset[2], *preset[3], *preset[4]}, }, { name: "list all items with current resource version and match=NotOlderThan", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.Everything, rv: list.ResourceVersion, rvMatch: metav1.ResourceVersionMatchNotOlderThan, @@ -1130,7 +1130,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "verify list returns updated version of object; filter returns one item, page size equal to total list size with current resource version and match=NotOlderThan", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("spec.nodeName", "fakeNode"), Label: labels.Everything(), @@ -1142,7 +1142,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "verify list does not return deleted object; filter for deleted object, page size equal to total list size with current resource version and match=NotOlderThan", - prefix: "/pods", + prefix: KeyFunc("", ""), pred: storage.SelectionPredicate{ Field: fields.OneTermEqualSelector("metadata.name", "baz"), Label: labels.Everything(), @@ -1154,7 +1154,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test consistent List", - prefix: "/pods/empty", + prefix: KeyFunc("empty", ""), pred: storage.Everything, rv: "", expectRV: currentRV, @@ -1162,7 +1162,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, { name: "test non-consistent List", - prefix: "/pods/empty", + prefix: KeyFunc("empty", ""), pred: storage.Everything, rv: "0", expectRVFunc: resourceVersionNotOlderThan(list.ResourceVersion), @@ -1293,7 +1293,7 @@ func RunTestConsistentList(ctx context.Context, t *testing.T, store storage.Inte ResourceVersion: tc.requestRV, Predicate: storage.Everything, } - err = store.GetList(ctx, "/pods/empty", opts, out) + err = store.GetList(ctx, KeyFunc("empty", ""), opts, out) if err != nil { t.Fatalf("GetList failed: %v", err) } @@ -1360,7 +1360,7 @@ func seedMultiLevelData(ctx context.Context, store storage.Interface) (string, [ // we want to figure out the resourceVersion before we create anything initialList := &example.PodList{} - if err := store.GetList(ctx, "/pods", storage.ListOptions{Predicate: storage.Everything, Recursive: true}, initialList); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), storage.ListOptions{Predicate: storage.Everything, Recursive: true}, initialList); err != nil { return "", nil, fmt.Errorf("failed to determine starting resourceVersion: %w", err) } initialRV := initialList.ResourceVersion @@ -1582,25 +1582,25 @@ func RunTestGetListRecursivePrefix(ctx context.Context, t *testing.T, store stor }{ { name: "NonRecursive on resource prefix doesn't return any objects", - key: "/pods/", + key: KeyFunc("", ""), recursive: false, expectedOut: []example.Pod{}, }, { name: "Recursive on resource prefix returns all objects", - key: "/pods/", + key: KeyFunc("", ""), recursive: true, expectedOut: []example.Pod{*fooObj, *fooBarObj, *otherNamespaceObj}, }, { name: "NonRecursive on namespace prefix doesn't return any objects", - key: "/pods/test-ns/", + key: KeyFunc("test-ns", ""), recursive: false, expectedOut: []example.Pod{}, }, { name: "Recursive on resource prefix returns objects in the namespace", - key: "/pods/test-ns/", + key: KeyFunc("test-ns", ""), recursive: true, expectedOut: []example.Pod{*fooObj, *fooBarObj}, }, @@ -1739,7 +1739,7 @@ func RunTestListContinuation(ctx context.Context, t *testing.T, store storage.In Predicate: pred(1, ""), Recursive: true, } - if err := store.GetList(ctx, "/pods", options, out); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, out); err != nil { t.Fatalf("Unable to get initial list: %v", err) } if len(out.Continue) == 0 { @@ -1763,13 +1763,13 @@ func RunTestListContinuation(ctx context.Context, t *testing.T, store storage.In Predicate: pred(0, continueFromSecondItem), Recursive: true, } - if err := store.GetList(ctx, "/pods", options, out); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, out); err != nil { t.Fatalf("Unable to get second page: %v", err) } if len(out.Continue) != 0 { t.Fatalf("Unexpected continuation token set") } - key, rv, err := storage.DecodeContinue(continueFromSecondItem, "/pods") + key, rv, err := storage.DecodeContinue(continueFromSecondItem, KeyFunc("", "")) t.Logf("continue token was %d %s %v", rv, key, err) expectNoDiff(t, "incorrect second page", []example.Pod{*preset[1].storedObj, *preset[2].storedObj}, out.Items) if out.ResourceVersion != currentRV { @@ -1787,7 +1787,7 @@ func RunTestListContinuation(ctx context.Context, t *testing.T, store storage.In Predicate: pred(1, continueFromSecondItem), Recursive: true, } - if err := store.GetList(ctx, "/pods", options, out); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, out); err != nil { t.Fatalf("Unable to get second page: %v", err) } if len(out.Continue) == 0 { @@ -1810,7 +1810,7 @@ func RunTestListContinuation(ctx context.Context, t *testing.T, store storage.In Predicate: pred(1, continueFromThirdItem), Recursive: true, } - if err := store.GetList(ctx, "/pods", options, out); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, out); err != nil { t.Fatalf("Unable to get second page: %v", err) } if len(out.Continue) != 0 { @@ -1852,7 +1852,7 @@ func RunTestListPaginationRareObject(ctx context.Context, t *testing.T, store st }, Recursive: true, } - if err := store.GetList(ctx, "/pods", options, out); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, out); err != nil { t.Fatalf("Unable to get initial list: %v", err) } if len(out.Continue) != 0 { @@ -1928,7 +1928,7 @@ func RunTestListContinuationWithFilter(ctx context.Context, t *testing.T, store Predicate: pred(2, ""), Recursive: true, } - if err := store.GetList(ctx, "/pods", options, out); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, out); err != nil { t.Errorf("Unable to get initial list: %v", err) } if len(out.Continue) == 0 { @@ -1959,7 +1959,7 @@ func RunTestListContinuationWithFilter(ctx context.Context, t *testing.T, store Predicate: pred(2, cont), Recursive: true, } - if err := store.GetList(ctx, "/pods", options, out); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, out); err != nil { t.Errorf("Unable to get second page: %v", err) } if len(out.Continue) != 0 { @@ -2035,7 +2035,7 @@ func RunTestListInconsistentContinuation(ctx context.Context, t *testing.T, stor Predicate: pred(1, ""), Recursive: true, } - if err := store.GetList(ctx, "/pods", options, out); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, out); err != nil { t.Fatalf("Unable to get initial list: %v", err) } if len(out.Continue) == 0 { @@ -2072,7 +2072,7 @@ func RunTestListInconsistentContinuation(ctx context.Context, t *testing.T, stor Predicate: pred(0, continueFromSecondItem), Recursive: true, } - err := store.GetList(ctx, "/pods", options, out) + err := store.GetList(ctx, KeyFunc("", ""), options, out) if err == nil { t.Fatalf("unexpected no error") } @@ -2094,7 +2094,7 @@ func RunTestListInconsistentContinuation(ctx context.Context, t *testing.T, stor Predicate: pred(1, inconsistentContinueFromSecondItem), Recursive: true, } - if err := store.GetList(ctx, "/pods", options, out); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, out); err != nil { t.Fatalf("Unable to get second page: %v", err) } if len(out.Continue) == 0 { @@ -2113,7 +2113,7 @@ func RunTestListInconsistentContinuation(ctx context.Context, t *testing.T, stor Predicate: pred(1, continueFromThirdItem), Recursive: true, } - if err := store.GetList(ctx, "/pods", options, out); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, out); err != nil { t.Fatalf("Unable to get second page: %v", err) } if len(out.Continue) != 0 { @@ -2174,7 +2174,7 @@ func RunTestListResourceVersionMatch(ctx context.Context, t *testing.T, store In Predicate: predicate, Recursive: true, } - if err := store.GetList(ctx, "/pods", options, &result1); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, &result1); err != nil { t.Fatalf("failed to list objects: %v", err) } @@ -2187,7 +2187,7 @@ func RunTestListResourceVersionMatch(ctx context.Context, t *testing.T, store In } result2 := example.PodList{} - if err := store.GetList(ctx, "/pods", options, &result2); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, &result2); err != nil { t.Fatalf("failed to list objects: %v", err) } @@ -2197,7 +2197,7 @@ func RunTestListResourceVersionMatch(ctx context.Context, t *testing.T, store In options.ResourceVersionMatch = metav1.ResourceVersionMatchNotOlderThan result3 := example.PodList{} - if err := store.GetList(ctx, "/pods", options, &result3); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, &result3); err != nil { t.Fatalf("failed to list objects: %v", err) } @@ -2205,7 +2205,7 @@ func RunTestListResourceVersionMatch(ctx context.Context, t *testing.T, store In options.ResourceVersionMatch = metav1.ResourceVersionMatchExact result4 := example.PodList{} - if err := store.GetList(ctx, "/pods", options, &result4); err != nil { + if err := store.GetList(ctx, KeyFunc("", ""), options, &result4); err != nil { t.Fatalf("failed to list objects: %v", err) } @@ -2621,7 +2621,7 @@ func RunTestTransformationFailure(ctx context.Context, t *testing.T, store Inter Predicate: storage.Everything, Recursive: true, } - if err := store.GetList(ctx, "/pods", storageOpts, &got); !storage.IsInternalError(err) { + if err := store.GetList(ctx, KeyFunc("", ""), storageOpts, &got); !storage.IsInternalError(err) { t.Errorf("Unexpected error %v", err) }