mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 20:53:33 +00:00
Merge pull request #82303 from roycaihw/update-precondition-retry
In GuaranteedUpdate, retry on a precondition check failure if we are working with cached data
This commit is contained in:
commit
26a381b8e1
@ -1899,6 +1899,54 @@ func TestDeleteWithCachedObject(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPreconditionalUpdateWithCachedObject(t *testing.T) {
|
||||||
|
podName := "foo"
|
||||||
|
pod := &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 has old UID
|
||||||
|
oldPod, err := registry.Create(ctx, pod, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
registry.Storage.Storage = &staleGuaranteedUpdateStorage{Interface: registry.Storage.Storage, cachedObj: oldPod}
|
||||||
|
|
||||||
|
// delete and re-create the same object with new UID
|
||||||
|
_, _, err = registry.Delete(ctx, podName, rest.ValidateAllObjectFunc, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
obj, err := registry.Create(ctx, pod, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
newPod, ok := obj.(*example.Pod)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("unexpected object: %#v", obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the object should not fail precondition
|
||||||
|
newPod.Spec.NodeName = "machine2"
|
||||||
|
res, _, err := registry.Update(ctx, podName, rest.DefaultUpdatedObjectInfo(newPod), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// the update should have succeeded
|
||||||
|
r, ok := res.(*example.Pod)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("unexpected update result: %#v", res)
|
||||||
|
}
|
||||||
|
if r.Spec.NodeName != "machine2" {
|
||||||
|
t.Fatalf("unexpected, update didn't take effect: %#v", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestRetryDeleteValidation checks if the deleteValidation is called again if
|
// TestRetryDeleteValidation checks if the deleteValidation is called again if
|
||||||
// the GuaranteedUpdate in the Delete handler conflicts with a simultaneous
|
// the GuaranteedUpdate in the Delete handler conflicts with a simultaneous
|
||||||
// Update.
|
// Update.
|
||||||
|
@ -274,7 +274,20 @@ func (s *store) GuaranteedUpdate(
|
|||||||
transformContext := authenticatedDataString(key)
|
transformContext := authenticatedDataString(key)
|
||||||
for {
|
for {
|
||||||
if err := preconditions.Check(key, origState.obj); err != nil {
|
if err := preconditions.Check(key, origState.obj); err != nil {
|
||||||
return err
|
// If our data is already up to date, return the error
|
||||||
|
if !mustCheckData {
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, ttl, err := s.updateState(origState, tryUpdate)
|
ret, ttl, err := s.updateState(origState, tryUpdate)
|
||||||
|
Loading…
Reference in New Issue
Block a user