Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
In GuaranteedUpdate, retry on any error if we are working with stale …
…data
  • Loading branch information
Chao Xu committed May 9, 2019
1 parent 71bbabc commit 5e53522
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 11 deletions.
Expand Up @@ -1851,3 +1851,47 @@ func TestMarkAsDeleting(t *testing.T) {
})
}
}

type staleGuaranteedUpdateStorage struct {
storage.Interface
cachedObj runtime.Object
}

// GuaranteedUpdate overwrites the method with one that always suggests the cachedObj.
func (s *staleGuaranteedUpdateStorage) GuaranteedUpdate(
ctx context.Context, key string, ptrToType runtime.Object, ignoreNotFound bool,
preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, _ ...runtime.Object) error {
return s.Interface.GuaranteedUpdate(ctx, key, ptrToType, ignoreNotFound, preconditions, tryUpdate, s.cachedObj)
}

func TestDeleteWithCachedObject(t *testing.T) {
podName := "foo"
podWithFinalizer := &example.Pod{
ObjectMeta: metav1.ObjectMeta{Name: podName, Finalizers: []string{"foo.com/x"}},
Spec: example.PodSpec{NodeName: "machine"},
}
podWithNoFinalizer := &example.Pod{
ObjectMeta: metav1.ObjectMeta{Name: podName},
Spec: example.PodSpec{NodeName: "machine"},
}
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test")
destroyFunc, registry := newTestGenericStoreRegistry(t, scheme, false)
defer destroyFunc()
// cached object does not have any finalizer.
registry.Storage.Storage = &staleGuaranteedUpdateStorage{Interface: registry.Storage.Storage, cachedObj: podWithNoFinalizer}
// created object with pending finalizer.
_, err := registry.Create(ctx, podWithFinalizer, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
if err != nil {
t.Fatal(err)
}
// The object shouldn't be deleted, because the persisted object has pending finalizers.
_, _, err = registry.Delete(ctx, podName, nil)
if err != nil {
t.Fatal(err)
}
// The object should still be there
_, err = registry.Get(ctx, podName, &metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}
}
23 changes: 12 additions & 11 deletions staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go
Expand Up @@ -301,19 +301,20 @@ func (s *store) GuaranteedUpdate(

ret, ttl, err := s.updateState(origState, tryUpdate)
if err != nil {
// It's possible we were working with stale data
if mustCheckData && apierrors.IsConflict(err) {
// Actually fetch
origState, err = getCurrentState()
if err != nil {
return err
}
mustCheckData = false
// Retry
continue
// If our data is already up to date, return the error
if !mustCheckData {
return err
}

return err
// It's possible we were working with stale data
// Actually fetch
origState, err = getCurrentState()
if err != nil {
return err
}
mustCheckData = false
// Retry
continue
}

data, err := runtime.Encode(s.codec, ret)
Expand Down

0 comments on commit 5e53522

Please sign in to comment.