refactor: add delete options for Delete method in storage interface

Kubernetes-commit: bc0ea34bc380e073a7278216fe6690a1b9aee48c
This commit is contained in:
Abu Kashem 2024-09-19 10:31:08 -04:00 committed by Kubernetes Publisher
parent 664cde1f32
commit 3a0975b22c
12 changed files with 43 additions and 37 deletions

View File

@ -337,7 +337,7 @@ func (r *peerEndpointLeaseReconciler) StopReconciling() {
// different ports
func (r *peerEndpointLeaseReconciler) RemoveLease(serverId string) error {
key := path.Join(r.serverLeases.baseKey, serverId)
return r.serverLeases.storage.Delete(apirequest.NewDefaultContext(), key, &corev1.Endpoints{}, nil, rest.ValidateAllObjectFunc, nil)
return r.serverLeases.storage.Delete(apirequest.NewDefaultContext(), key, &corev1.Endpoints{}, nil, rest.ValidateAllObjectFunc, nil, storage.DeleteOptions{})
}
func (r *peerEndpointLeaseReconciler) Destroy() {

View File

@ -46,7 +46,7 @@ func (s *DryRunnableStorage) Create(ctx context.Context, key string, obj, out ru
return s.Storage.Create(ctx, key, obj, out, ttl)
}
func (s *DryRunnableStorage) Delete(ctx context.Context, key string, out runtime.Object, preconditions *storage.Preconditions, deleteValidation storage.ValidateObjectFunc, dryRun bool, cachedExistingObject runtime.Object) error {
func (s *DryRunnableStorage) Delete(ctx context.Context, key string, out runtime.Object, preconditions *storage.Preconditions, deleteValidation storage.ValidateObjectFunc, dryRun bool, cachedExistingObject runtime.Object, opts storage.DeleteOptions) error {
if dryRun {
if err := s.Storage.Get(ctx, key, storage.GetOptions{}, out); err != nil {
return err
@ -56,7 +56,7 @@ func (s *DryRunnableStorage) Delete(ctx context.Context, key string, out runtime
}
return deleteValidation(ctx, out)
}
return s.Storage.Delete(ctx, key, out, preconditions, deleteValidation, cachedExistingObject)
return s.Storage.Delete(ctx, key, out, preconditions, deleteValidation, cachedExistingObject, opts)
}
func (s *DryRunnableStorage) Watch(ctx context.Context, key string, opts storage.ListOptions) (watch.Interface, error) {

View File

@ -238,7 +238,7 @@ func TestDryRunDeleteDoesntDelete(t *testing.T) {
t.Fatalf("Failed to create new object: %v", err)
}
err = s.Delete(context.Background(), "key", out, nil, rest.ValidateAllObjectFunc, true, nil)
err = s.Delete(context.Background(), "key", out, nil, rest.ValidateAllObjectFunc, true, nil, storage.DeleteOptions{})
if err != nil {
t.Fatalf("Failed to dry-run delete the object: %v", err)
}
@ -254,7 +254,7 @@ func TestDryRunDeleteMissingObjectFails(t *testing.T) {
defer destroy()
out := UnstructuredOrDie(`{}`)
err := s.Delete(context.Background(), "key", out, nil, rest.ValidateAllObjectFunc, true, nil)
err := s.Delete(context.Background(), "key", out, nil, rest.ValidateAllObjectFunc, true, nil, storage.DeleteOptions{})
if e, ok := err.(*storage.StorageError); !ok || e.Code != storage.ErrCodeKeyNotFound {
t.Errorf("Expected key to be not found, error: %v", err)
}
@ -274,7 +274,7 @@ func TestDryRunDeleteReturnsObject(t *testing.T) {
out = UnstructuredOrDie(`{}`)
expected := UnstructuredOrDie(`{"kind": "Pod", "metadata": {"resourceVersion": "2"}}`)
err = s.Delete(context.Background(), "key", out, nil, rest.ValidateAllObjectFunc, true, nil)
err = s.Delete(context.Background(), "key", out, nil, rest.ValidateAllObjectFunc, true, nil, storage.DeleteOptions{})
if err != nil {
t.Fatalf("Failed to delete with valid precondition: %v", err)
}
@ -297,12 +297,12 @@ func TestDryRunDeletePreconditions(t *testing.T) {
wrongID := types.UID("wrong-uid")
myID := types.UID("my-uid")
err = s.Delete(context.Background(), "key", out, &storage.Preconditions{UID: &wrongID}, rest.ValidateAllObjectFunc, true, nil)
err = s.Delete(context.Background(), "key", out, &storage.Preconditions{UID: &wrongID}, rest.ValidateAllObjectFunc, true, nil, storage.DeleteOptions{})
if e, ok := err.(*storage.StorageError); !ok || e.Code != storage.ErrCodeInvalidObj {
t.Errorf("Expected invalid object, error: %v", err)
}
err = s.Delete(context.Background(), "key", out, &storage.Preconditions{UID: &myID}, rest.ValidateAllObjectFunc, true, nil)
err = s.Delete(context.Background(), "key", out, &storage.Preconditions{UID: &myID}, rest.ValidateAllObjectFunc, true, nil, storage.DeleteOptions{})
if err != nil {
t.Fatalf("Failed to delete with valid precondition: %v", err)
}

View File

@ -572,7 +572,7 @@ func (e *Store) deleteWithoutFinalizers(ctx context.Context, name, key string, o
out := e.NewFunc()
klog.V(6).InfoS("Going to delete object from registry, triggered by update", "object", klog.KRef(genericapirequest.NamespaceValue(ctx), name))
// Using the rest.ValidateAllObjectFunc because the request is an UPDATE request and has already passed the admission for the UPDATE verb.
if err := e.Storage.Delete(ctx, key, out, preconditions, rest.ValidateAllObjectFunc, dryrun.IsDryRun(options.DryRun), nil); err != nil {
if err := e.Storage.Delete(ctx, key, out, preconditions, rest.ValidateAllObjectFunc, dryrun.IsDryRun(options.DryRun), nil, storage.DeleteOptions{}); err != nil {
// Deletion is racy, i.e., there could be multiple update
// requests to remove all finalizers from the object, so we
// ignore the NotFound error.
@ -1182,7 +1182,7 @@ func (e *Store) Delete(ctx context.Context, name string, deleteValidation rest.V
// delete immediately, or no graceful deletion supported
klog.V(6).InfoS("Going to delete object from registry", "object", klog.KRef(genericapirequest.NamespaceValue(ctx), name))
out = e.NewFunc()
if err := e.Storage.Delete(ctx, key, out, &preconditions, storage.ValidateObjectFunc(deleteValidation), dryrun.IsDryRun(options.DryRun), nil); err != nil {
if err := e.Storage.Delete(ctx, key, out, &preconditions, storage.ValidateObjectFunc(deleteValidation), dryrun.IsDryRun(options.DryRun), nil, storage.DeleteOptions{}); err != nil {
// Please refer to the place where we set ignoreNotFound for the reason
// why we ignore the NotFound error .
if storage.IsNotFound(err) && ignoreNotFound && lastExisting != nil {

View File

@ -492,7 +492,7 @@ func (c *Cacher) Create(ctx context.Context, key string, obj, out runtime.Object
// Delete implements storage.Interface.
func (c *Cacher) Delete(
ctx context.Context, key string, out runtime.Object, preconditions *storage.Preconditions,
validateDeletion storage.ValidateObjectFunc, _ runtime.Object) error {
validateDeletion storage.ValidateObjectFunc, _ runtime.Object, opts storage.DeleteOptions) error {
// Ignore the suggestion and try to pass down the current version of the object
// read from cache.
if elem, exists, err := c.watchCache.GetByKey(key); err != nil {
@ -501,10 +501,10 @@ func (c *Cacher) Delete(
// DeepCopy the object since we modify resource version when serializing the
// current object.
currObj := elem.(*storeElement).Object.DeepCopyObject()
return c.storage.Delete(ctx, key, out, preconditions, validateDeletion, currObj)
return c.storage.Delete(ctx, key, out, preconditions, validateDeletion, currObj, opts)
}
// If we couldn't get the object, fallback to no-suggestion.
return c.storage.Delete(ctx, key, out, preconditions, validateDeletion, nil)
return c.storage.Delete(ctx, key, out, preconditions, validateDeletion, nil, opts)
}
type namespacedName struct {

View File

@ -152,7 +152,7 @@ func (d *dummyStorage) Versioner() storage.Versioner { return nil }
func (d *dummyStorage) Create(_ context.Context, _ string, _, _ runtime.Object, _ uint64) error {
return fmt.Errorf("unimplemented")
}
func (d *dummyStorage) Delete(_ context.Context, _ string, _ runtime.Object, _ *storage.Preconditions, _ storage.ValidateObjectFunc, _ runtime.Object) error {
func (d *dummyStorage) Delete(_ context.Context, _ string, _ runtime.Object, _ *storage.Preconditions, _ storage.ValidateObjectFunc, _ runtime.Object, _ storage.DeleteOptions) error {
return fmt.Errorf("unimplemented")
}
func (d *dummyStorage) Watch(ctx context.Context, key string, opts storage.ListOptions) (watch.Interface, error) {
@ -2798,7 +2798,7 @@ func TestWatchStreamSeparation(t *testing.T) {
if err != nil {
t.Fatal(err)
}
err = cacher.Delete(context.Background(), "foo", &out, nil, storage.ValidateAllObjectFunc, &example.Pod{})
err = cacher.Delete(context.Background(), "foo", &out, nil, storage.ValidateAllObjectFunc, &example.Pod{}, storage.DeleteOptions{})
if err != nil {
t.Fatal(err)
}

View File

@ -262,7 +262,7 @@ func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object,
// Delete implements storage.Interface.Delete.
func (s *store) Delete(
ctx context.Context, key string, out runtime.Object, preconditions *storage.Preconditions,
validateDeletion storage.ValidateObjectFunc, cachedExistingObject runtime.Object) error {
validateDeletion storage.ValidateObjectFunc, cachedExistingObject runtime.Object, opts storage.DeleteOptions) error {
preparedKey, err := s.prepareKey(key)
if err != nil {
return err

View File

@ -646,7 +646,7 @@ func TestInvalidKeys(t *testing.T) {
ctx, store, _ := testSetup(t)
expectInvalidKey("Create", store.Create(ctx, invalidKey, nil, nil, 0))
expectInvalidKey("Delete", store.Delete(ctx, invalidKey, nil, nil, nil, nil))
expectInvalidKey("Delete", store.Delete(ctx, invalidKey, nil, nil, nil, nil, storage.DeleteOptions{}))
_, watchErr := store.Watch(ctx, invalidKey, storage.ListOptions{})
expectInvalidKey("Watch", watchErr)
expectInvalidKey("Get", store.Get(ctx, invalidKey, storage.GetOptions{}, nil))

View File

@ -180,7 +180,7 @@ type Interface interface {
// However, the implementations have to retry in case suggestion is stale.
Delete(
ctx context.Context, key string, out runtime.Object, preconditions *Preconditions,
validateDeletion ValidateObjectFunc, cachedExistingObject runtime.Object) error
validateDeletion ValidateObjectFunc, cachedExistingObject runtime.Object, opts DeleteOptions) error
// Watch begins watching the specified key. Events are decoded into API objects,
// and any items selected by 'p' are sent down to returned watch.Interface.
@ -314,3 +314,7 @@ type ListOptions struct {
// continues streaming events.
SendInitialEvents *bool
}
// DeleteOptions provides the options that may be provided for storage delete operations.
type DeleteOptions struct {
}

View File

@ -260,7 +260,7 @@ func RunTestUnconditionalDelete(ctx context.Context, t *testing.T, store storage
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out := &example.Pod{} // reset
err := store.Delete(ctx, tt.key, out, nil, storage.ValidateAllObjectFunc, nil)
err := store.Delete(ctx, tt.key, out, nil, storage.ValidateAllObjectFunc, nil, storage.DeleteOptions{})
if tt.expectNotFoundErr {
if err == nil || !storage.IsNotFound(err) {
t.Errorf("expecting not found error, but get: %s", err)
@ -302,7 +302,7 @@ func RunTestConditionalDelete(ctx context.Context, t *testing.T, store storage.I
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out := &example.Pod{}
err := store.Delete(ctx, key, out, tt.precondition, storage.ValidateAllObjectFunc, nil)
err := store.Delete(ctx, key, out, tt.precondition, storage.ValidateAllObjectFunc, nil, storage.DeleteOptions{})
if tt.expectInvalidObjErr {
if err == nil || !storage.IsInvalidObj(err) {
t.Errorf("expecting invalid UID error, but get: %s", err)
@ -354,7 +354,7 @@ func RunTestDeleteWithSuggestion(ctx context.Context, t *testing.T, store storag
key, originalPod := testPropagateStore(ctx, t, store, &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "name", Namespace: "test-ns"}})
out := &example.Pod{}
if err := store.Delete(ctx, key, out, nil, storage.ValidateAllObjectFunc, originalPod); err != nil {
if err := store.Delete(ctx, key, out, nil, storage.ValidateAllObjectFunc, originalPod, storage.DeleteOptions{}); err != nil {
t.Errorf("Unexpected failure during deletion: %v", err)
}
@ -378,7 +378,7 @@ func RunTestDeleteWithSuggestionAndConflict(ctx context.Context, t *testing.T, s
}
out := &example.Pod{}
if err := store.Delete(ctx, key, out, nil, storage.ValidateAllObjectFunc, originalPod); err != nil {
if err := store.Delete(ctx, key, out, nil, storage.ValidateAllObjectFunc, originalPod, storage.DeleteOptions{}); err != nil {
t.Errorf("Unexpected failure during deletion: %v", err)
}
@ -416,7 +416,7 @@ func RunTestDeleteWithConflict(ctx context.Context, t *testing.T, store storage.
}
out := &example.Pod{}
if err := store.Delete(ctx, key, out, nil, validateAllWithUpdate, nil); err != nil {
if err := store.Delete(ctx, key, out, nil, validateAllWithUpdate, nil, storage.DeleteOptions{}); err != nil {
t.Errorf("Unexpected failure during deletion: %v", err)
}
@ -439,13 +439,13 @@ func RunTestDeleteWithSuggestionOfDeletedObject(ctx context.Context, t *testing.
// First delete, so originalPod is outdated.
deletedPod := &example.Pod{}
if err := store.Delete(ctx, key, deletedPod, nil, storage.ValidateAllObjectFunc, originalPod); err != nil {
if err := store.Delete(ctx, key, deletedPod, nil, storage.ValidateAllObjectFunc, originalPod, storage.DeleteOptions{}); err != nil {
t.Errorf("Unexpected failure during deletion: %v", err)
}
// Now try deleting with stale object.
out := &example.Pod{}
if err := store.Delete(ctx, key, out, nil, storage.ValidateAllObjectFunc, originalPod); !storage.IsNotFound(err) {
if err := store.Delete(ctx, key, out, nil, storage.ValidateAllObjectFunc, originalPod, storage.DeleteOptions{}); !storage.IsNotFound(err) {
t.Errorf("Unexpected error during deletion: %v, expected not-found", err)
}
}
@ -461,7 +461,8 @@ func RunTestValidateDeletionWithSuggestion(ctx context.Context, t *testing.T, st
return validationError
}
out := &example.Pod{}
if err := store.Delete(ctx, key, out, nil, validateNothing, originalPod); err != validationError {
// nolint:errorlint // not changing the level of assertion
if err := store.Delete(ctx, key, out, nil, validateNothing, originalPod, storage.DeleteOptions{}); err != validationError {
t.Errorf("Unexpected failure during deletion: %v", err)
}
if validationCalls != 1 {
@ -489,7 +490,7 @@ func RunTestValidateDeletionWithSuggestion(ctx context.Context, t *testing.T, st
return nil
}
if err := store.Delete(ctx, key, out, nil, validateFresh, originalPod); err != nil {
if err := store.Delete(ctx, key, out, nil, validateFresh, originalPod, storage.DeleteOptions{}); err != nil {
t.Errorf("Unexpected failure during deletion: %v", err)
}
@ -517,7 +518,8 @@ func RunTestValidateDeletionWithOnlySuggestionValid(ctx context.Context, t *test
return validationError
}
out := &example.Pod{}
if err := store.Delete(ctx, key, out, nil, validateNothing, originalPod); err != validationError {
// nolint:errorlint // not changing the level of assertion
if err := store.Delete(ctx, key, out, nil, validateNothing, originalPod, storage.DeleteOptions{}); err != validationError {
t.Errorf("Unexpected failure during deletion: %v", err)
}
if validationCalls != 1 {
@ -545,7 +547,7 @@ func RunTestValidateDeletionWithOnlySuggestionValid(ctx context.Context, t *test
return nil
}
err := store.Delete(ctx, key, out, nil, validateFresh, originalPod)
err := store.Delete(ctx, key, out, nil, validateFresh, originalPod, storage.DeleteOptions{})
if err == nil || err.Error() != "stale object" {
t.Errorf("expecting stale object error, but get: %s", err)
}
@ -579,7 +581,7 @@ func RunTestPreconditionalDeleteWithSuggestion(ctx context.Context, t *testing.T
prec := storage.NewUIDPreconditions("myUID")
out := &example.Pod{}
if err := store.Delete(ctx, key, out, prec, storage.ValidateAllObjectFunc, originalPod); err != nil {
if err := store.Delete(ctx, key, out, prec, storage.ValidateAllObjectFunc, originalPod, storage.DeleteOptions{}); err != nil {
t.Errorf("Unexpected failure during deletion: %v", err)
}
@ -608,7 +610,7 @@ func RunTestPreconditionalDeleteWithOnlySuggestionPass(ctx context.Context, t *t
// Although originalPod passes the precondition, its delete would fail due to conflict.
// The 2nd try with updatedPod would fail the precondition.
out := &example.Pod{}
err := store.Delete(ctx, key, out, prec, storage.ValidateAllObjectFunc, originalPod)
err := store.Delete(ctx, key, out, prec, storage.ValidateAllObjectFunc, originalPod, storage.DeleteOptions{})
if err == nil || !storage.IsInvalidObj(err) {
t.Errorf("expecting invalid UID error, but get: %s", err)
}
@ -1401,7 +1403,7 @@ func seedMultiLevelData(ctx context.Context, store storage.Interface) (string, [
// We now delete bazSecond provided it has been created first. We do this to enable
// testing cases that had an object exist initially and then was deleted and how this
// would be reflected in responses of different calls.
if err := store.Delete(ctx, computePodKey(bazSecond), preset[len(preset)-1].storedObj, nil, storage.ValidateAllObjectFunc, nil); err != nil {
if err := store.Delete(ctx, computePodKey(bazSecond), preset[len(preset)-1].storedObj, nil, storage.ValidateAllObjectFunc, nil, storage.DeleteOptions{}); err != nil {
return "", nil, fmt.Errorf("failed to delete object: %w", err)
}
@ -2661,7 +2663,7 @@ func RunTestTransformationFailure(ctx context.Context, t *testing.T, store Inter
}
// Delete fails with internal error.
if err := store.Delete(ctx, preset[1].key, &example.Pod{}, nil, storage.ValidateAllObjectFunc, nil); !storage.IsInternalError(err) {
if err := store.Delete(ctx, preset[1].key, &example.Pod{}, nil, storage.ValidateAllObjectFunc, nil, storage.DeleteOptions{}); !storage.IsInternalError(err) {
t.Errorf("Unexpected error: %v", err)
}
if err := store.Get(ctx, preset[1].key, storage.GetOptions{}, &example.Pod{}); !storage.IsInternalError(err) {

View File

@ -89,7 +89,7 @@ func testPropagateStore(ctx context.Context, t *testing.T, store storage.Interfa
key := computePodKey(obj)
// Setup store with the specified key and grab the output for returning.
err := store.Delete(ctx, key, &example.Pod{}, nil, storage.ValidateAllObjectFunc, nil)
err := store.Delete(ctx, key, &example.Pod{}, nil, storage.ValidateAllObjectFunc, nil, storage.DeleteOptions{})
if err != nil && !storage.IsNotFound(err) {
t.Fatalf("Cleanup failed: %v", err)
}

View File

@ -177,7 +177,7 @@ func testWatch(ctx context.Context, t *testing.T, store storage.Interface, recur
t.Fatalf("GuaranteedUpdate failed: %v", err)
}
} else {
err := store.Delete(ctx, key, out, nil, storage.ValidateAllObjectFunc, nil)
err := store.Delete(ctx, key, out, nil, storage.ValidateAllObjectFunc, nil, storage.DeleteOptions{})
if err != nil {
t.Fatalf("Delete failed: %v", err)
}
@ -294,7 +294,7 @@ func RunTestDeleteTriggerWatch(ctx context.Context, t *testing.T, store storage.
if err != nil {
t.Fatalf("Watch failed: %v", err)
}
if err := store.Delete(ctx, key, &example.Pod{}, nil, storage.ValidateAllObjectFunc, nil); err != nil {
if err := store.Delete(ctx, key, &example.Pod{}, nil, storage.ValidateAllObjectFunc, nil, storage.DeleteOptions{}); err != nil {
t.Fatalf("Delete failed: %v", err)
}
testCheckEventType(t, w, watch.Deleted)
@ -498,7 +498,7 @@ func RunTestWatchDeleteEventObjectHaveLatestRV(ctx context.Context, t *testing.T
}
deletedObj := &example.Pod{}
if err := store.Delete(ctx, key, deletedObj, &storage.Preconditions{}, storage.ValidateAllObjectFunc, nil); err != nil {
if err := store.Delete(ctx, key, deletedObj, &storage.Preconditions{}, storage.ValidateAllObjectFunc, nil, storage.DeleteOptions{}); err != nil {
t.Fatalf("Delete failed: %v", err)
}