mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 10:20:51 +00:00
prevent mutation of deletion options during delete collection
This commit is contained in:
parent
b765496650
commit
649b87aaf8
@ -982,6 +982,7 @@ func (e *Store) updateForGracefulDeletionAndFinalizers(ctx context.Context, name
|
||||
}
|
||||
|
||||
// Delete removes the item from storage.
|
||||
// options can be mutated by rest.BeforeDelete due to a graceful deletion strategy.
|
||||
func (e *Store) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
|
||||
key, err := e.KeyFunc(ctx, name)
|
||||
if err != nil {
|
||||
@ -1148,7 +1149,11 @@ func (e *Store) DeleteCollection(ctx context.Context, deleteValidation rest.Vali
|
||||
errs <- err
|
||||
return
|
||||
}
|
||||
if _, _, err := e.Delete(ctx, accessor.GetName(), deleteValidation, options); err != nil && !apierrors.IsNotFound(err) {
|
||||
// DeepCopy the deletion options because individual graceful deleters communicate changes via a mutating
|
||||
// function in the delete strategy called in the delete method. While that is always ugly, it works
|
||||
// when making a single call. When making multiple calls via delete collection, the mutation applied to
|
||||
// pod/A can change the option ultimately used for pod/B.
|
||||
if _, _, err := e.Delete(ctx, accessor.GetName(), deleteValidation, options.DeepCopy()); err != nil && !apierrors.IsNotFound(err) {
|
||||
klog.V(4).InfoS("Delete object in DeleteCollection failed", "object", klog.KObj(accessor), "err", err)
|
||||
errs <- err
|
||||
return
|
||||
|
@ -86,6 +86,16 @@ func (t *testOrphanDeleteStrategy) DefaultGarbageCollectionPolicy(ctx context.Co
|
||||
return rest.OrphanDependents
|
||||
}
|
||||
|
||||
type mutatingDeleteRESTStrategy struct {
|
||||
runtime.ObjectTyper
|
||||
}
|
||||
|
||||
func (t *mutatingDeleteRESTStrategy) CheckGracefulDelete(ctx context.Context, obj runtime.Object, options *metav1.DeleteOptions) bool {
|
||||
n := int64(10)
|
||||
options.GracePeriodSeconds = &n
|
||||
return true
|
||||
}
|
||||
|
||||
type testRESTStrategy struct {
|
||||
runtime.ObjectTyper
|
||||
names.NameGenerator
|
||||
@ -2041,6 +2051,36 @@ func TestStoreDeleteCollection(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreDeleteCollectionNoMutateOptions(t *testing.T) {
|
||||
podA := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}
|
||||
podB := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}
|
||||
|
||||
testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test")
|
||||
destroyFunc, registry := NewTestGenericStoreRegistry(t)
|
||||
registry.DeleteStrategy = &mutatingDeleteRESTStrategy{scheme}
|
||||
defer destroyFunc()
|
||||
|
||||
if _, err := registry.Create(testContext, podA, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if _, err := registry.Create(testContext, podB, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
n := int64(50)
|
||||
inputDeleteOptions := &metav1.DeleteOptions{GracePeriodSeconds: &n}
|
||||
safeCopyOfDelete := inputDeleteOptions.DeepCopy()
|
||||
// Delete all pods.
|
||||
_, err := registry.DeleteCollection(testContext, rest.ValidateAllObjectFunc, inputDeleteOptions, &metainternalversion.ListOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(inputDeleteOptions, safeCopyOfDelete) {
|
||||
t.Error(inputDeleteOptions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreDeleteCollectionNotFound(t *testing.T) {
|
||||
destroyFunc, registry := NewTestGenericStoreRegistry(t)
|
||||
defer destroyFunc()
|
||||
|
@ -474,9 +474,12 @@ func noPodsInNamespace(c clientset.Interface, podNamespace string) wait.Conditio
|
||||
}
|
||||
|
||||
// cleanupPodsInNamespace deletes the pods in the given namespace and waits for them to
|
||||
// be actually deleted.
|
||||
// be actually deleted. They are removed with no grace.
|
||||
func cleanupPodsInNamespace(cs clientset.Interface, t *testing.T, ns string) {
|
||||
if err := cs.CoreV1().Pods(ns).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{}); err != nil {
|
||||
t.Helper()
|
||||
|
||||
zero := int64(0)
|
||||
if err := cs.CoreV1().Pods(ns).DeleteCollection(context.TODO(), metav1.DeleteOptions{GracePeriodSeconds: &zero}, metav1.ListOptions{}); err != nil {
|
||||
t.Errorf("error while listing pod in namespace %v: %v", ns, err)
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user