mirror of https://github.com/k3s-io/k3s
add validation rule to prevent adding finalizers if the object is being deleted
parent
f61a677a4e
commit
c5e1decc13
|
@ -438,6 +438,11 @@ func ValidateObjectMetaUpdate(newMeta, oldMeta *api.ObjectMeta, fldPath *field.P
|
|||
allErrs = append(allErrs, field.Invalid(fldPath.Child("deletionTimestamp"), newMeta.DeletionTimestamp, "field is immutable; may only be changed via deletion"))
|
||||
}
|
||||
|
||||
// Finalizers cannot be added if the object is already being deleted.
|
||||
if oldMeta.DeletionTimestamp != nil {
|
||||
allErrs = append(allErrs, ValidateNoNewFinalizers(newMeta.Finalizers, oldMeta.Finalizers, fldPath.Child("finalizers"))...)
|
||||
}
|
||||
|
||||
// Reject updates that don't specify a resource version
|
||||
if len(newMeta.ResourceVersion) == 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceVersion"), newMeta.ResourceVersion, "must be specified for an update"))
|
||||
|
@ -461,6 +466,16 @@ func ValidateObjectMetaUpdate(newMeta, oldMeta *api.ObjectMeta, fldPath *field.P
|
|||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateNoNewFinalizers(newFinalizers []string, oldFinalizers []string, fldPath *field.Path) field.ErrorList {
|
||||
const newFinalizersErrorMsg string = `no new finalizers can be added if the object is being deleted`
|
||||
allErrs := field.ErrorList{}
|
||||
extra := sets.NewString(newFinalizers...).Difference(sets.NewString(oldFinalizers...))
|
||||
if len(extra) != 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath, fmt.Sprintf("no new finalizers can be added if the object is being deleted, found new finalizers %#v", extra.List())))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateVolumes(volumes []api.Volume, fldPath *field.Path) (sets.String, field.ErrorList) {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
|
|
|
@ -248,6 +248,45 @@ func TestValidateObjectMetaUpdateIgnoresCreationTimestamp(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestValidateFinalizersUpdate(t *testing.T) {
|
||||
testcases := map[string]struct {
|
||||
Old api.ObjectMeta
|
||||
New api.ObjectMeta
|
||||
ExpectedErr string
|
||||
}{
|
||||
"invalid adding finalizers": {
|
||||
Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &unversioned.Time{}, Finalizers: []string{"x/a"}},
|
||||
New: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &unversioned.Time{}, Finalizers: []string{"x/a", "y/b"}},
|
||||
ExpectedErr: "y/b",
|
||||
},
|
||||
"invalid changing finalizers": {
|
||||
Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &unversioned.Time{}, Finalizers: []string{"x/a"}},
|
||||
New: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &unversioned.Time{}, Finalizers: []string{"x/b"}},
|
||||
ExpectedErr: "x/b",
|
||||
},
|
||||
"valid removing finalizers": {
|
||||
Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &unversioned.Time{}, Finalizers: []string{"x/a", "y/b"}},
|
||||
New: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &unversioned.Time{}, Finalizers: []string{"x/a"}},
|
||||
ExpectedErr: "",
|
||||
},
|
||||
"valid adding finalizers for objects not being deleted": {
|
||||
Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", Finalizers: []string{"x/a"}},
|
||||
New: api.ObjectMeta{Name: "test", ResourceVersion: "1", Finalizers: []string{"x/a", "y/b"}},
|
||||
ExpectedErr: "",
|
||||
},
|
||||
}
|
||||
for name, tc := range testcases {
|
||||
errs := ValidateObjectMetaUpdate(&tc.New, &tc.Old, field.NewPath("field"))
|
||||
if len(errs) == 0 {
|
||||
if len(tc.ExpectedErr) != 0 {
|
||||
t.Errorf("case: %q, expected error to contain %q", name, tc.ExpectedErr)
|
||||
}
|
||||
} else if e, a := tc.ExpectedErr, errs.ToAggregate().Error(); !strings.Contains(a, e) {
|
||||
t.Errorf("case: %q, expected error to contain %q, got error %q", name, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateObjectMetaUpdatePreventsDeletionFieldMutation(t *testing.T) {
|
||||
now := unversioned.NewTime(time.Unix(1000, 0).UTC())
|
||||
later := unversioned.NewTime(time.Unix(2000, 0).UTC())
|
||||
|
|
Loading…
Reference in New Issue