diff --git a/plugin/pkg/admission/initialization/initialization.go b/plugin/pkg/admission/initialization/initialization.go index 8c56f51e3b3..a105fc012f4 100644 --- a/plugin/pkg/admission/initialization/initialization.go +++ b/plugin/pkg/admission/initialization/initialization.go @@ -208,6 +208,13 @@ func (i *initializer) Admit(a admission.Attributes) (err error) { } updated := accessor.GetInitializers() + // controllers deployed with an empty initializers.pending have their initializers set to nil + // but should be able to update without changing their manifest + if updated != nil && len(updated.Pending) == 0 && updated.Result == nil { + accessor.SetInitializers(nil) + updated = nil + } + existingAccessor, err := meta.Accessor(a.GetOldObject()) if err != nil { // if the old object does not have an accessor, but the new one does, error out @@ -222,9 +229,6 @@ func (i *initializer) Admit(a admission.Attributes) (err error) { glog.V(5).Infof("Modifying uninitialized resource %s", a.GetResource()) - if updated != nil && len(updated.Pending) == 0 && updated.Result == nil { - accessor.SetInitializers(nil) - } // because we are called before validation, we need to ensure the update transition is valid. if errs := validation.ValidateInitializersUpdate(updated, existing, initializerFieldPath); len(errs) > 0 { return errors.NewInvalid(a.GetKind().GroupKind(), a.GetName(), errs) diff --git a/plugin/pkg/admission/initialization/initialization_test.go b/plugin/pkg/admission/initialization/initialization_test.go index cd8728379f2..0832fe8d1be 100644 --- a/plugin/pkg/admission/initialization/initialization_test.go +++ b/plugin/pkg/admission/initialization/initialization_test.go @@ -152,6 +152,22 @@ func TestAdmitUpdate(t *testing.T) { newInitializers: &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init.k8s.io"}}}, err: "field is immutable once initialization has completed", }, + { + name: "empty initializer list is treated as nil initializer", + oldInitializers: nil, + newInitializers: &metav1.Initializers{}, + verifyUpdatedObj: func(obj runtime.Object) (bool, string) { + accessor, err := meta.Accessor(obj) + if err != nil { + return false, "cannot get accessor" + } + if accessor.GetInitializers() != nil { + return false, "expect nil initializers" + } + return true, "" + }, + err: "", + }, } plugin := initializer{