mirror of https://github.com/k3s-io/k3s
Merge pull request #25036 from kargakis/validate-generation-update
Automatic merge from submit-queue api: validate generation updates @bprashanth @liggitt PTALpull/6/head
commit
ec6181d5d3
|
@ -173,6 +173,7 @@ func (t *Tester) TestUpdate(valid runtime.Object, createFn CreateFunc, getFn Get
|
||||||
t.testUpdateWithWrongUID(copyOrDie(valid), createFn, getFn)
|
t.testUpdateWithWrongUID(copyOrDie(valid), createFn, getFn)
|
||||||
t.testUpdateRetrievesOldObject(copyOrDie(valid), createFn, getFn)
|
t.testUpdateRetrievesOldObject(copyOrDie(valid), createFn, getFn)
|
||||||
t.testUpdatePropagatesUpdatedObjectError(copyOrDie(valid), createFn, getFn)
|
t.testUpdatePropagatesUpdatedObjectError(copyOrDie(valid), createFn, getFn)
|
||||||
|
t.testUpdateIgnoreGenerationUpdates(copyOrDie(valid), createFn, getFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test deleting an object.
|
// Test deleting an object.
|
||||||
|
@ -613,6 +614,40 @@ func (t *Tester) testUpdatePropagatesUpdatedObjectError(obj runtime.Object, crea
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tester) testUpdateIgnoreGenerationUpdates(obj runtime.Object, createFn CreateFunc, getFn GetFunc) {
|
||||||
|
ctx := t.TestContext()
|
||||||
|
|
||||||
|
foo := copyOrDie(obj)
|
||||||
|
name := t.namer(8)
|
||||||
|
t.setObjectMeta(foo, name)
|
||||||
|
|
||||||
|
if err := createFn(ctx, foo); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
storedFoo, err := getFn(ctx, foo)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
older := copyOrDie(storedFoo)
|
||||||
|
olderMeta := t.getObjectMetaOrFail(older)
|
||||||
|
olderMeta.Generation = 2
|
||||||
|
|
||||||
|
_, _, err = t.storage.(rest.Updater).Update(t.TestContext(), olderMeta.Name, rest.DefaultUpdatedObjectInfo(older, api.Scheme))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedFoo, err := getFn(ctx, older)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if exp, got := int64(1), t.getObjectMetaOrFail(updatedFoo).Generation; exp != got {
|
||||||
|
t.Errorf("Unexpected generation update: expected %d, got %d", exp, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tester) testUpdateOnNotFound(obj runtime.Object) {
|
func (t *Tester) testUpdateOnNotFound(obj runtime.Object) {
|
||||||
t.setObjectMeta(obj, t.namer(0))
|
t.setObjectMeta(obj, t.namer(0))
|
||||||
_, created, err := t.storage.(rest.Updater).Update(t.TestContext(), t.namer(0), rest.DefaultUpdatedObjectInfo(obj, api.Scheme))
|
_, created, err := t.storage.(rest.Updater).Update(t.TestContext(), t.namer(0), rest.DefaultUpdatedObjectInfo(obj, api.Scheme))
|
||||||
|
|
|
@ -86,6 +86,12 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx api.Context, obj, old runtime
|
||||||
} else {
|
} else {
|
||||||
objectMeta.Namespace = api.NamespaceNone
|
objectMeta.Namespace = api.NamespaceNone
|
||||||
}
|
}
|
||||||
|
// Ensure requests cannot update generation
|
||||||
|
oldMeta, err := api.ObjectMetaFor(old)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
objectMeta.Generation = oldMeta.Generation
|
||||||
|
|
||||||
strategy.PrepareForUpdate(obj, old)
|
strategy.PrepareForUpdate(obj, old)
|
||||||
|
|
||||||
|
|
|
@ -373,6 +373,11 @@ func ValidateObjectMetaUpdate(newMeta, oldMeta *api.ObjectMeta, fldPath *field.P
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceVersion"), newMeta.ResourceVersion, "must be specified for an update"))
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceVersion"), newMeta.ResourceVersion, "must be specified for an update"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generation shouldn't be decremented
|
||||||
|
if newMeta.Generation < oldMeta.Generation {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("generation"), newMeta.Generation, "must not be decremented"))
|
||||||
|
}
|
||||||
|
|
||||||
allErrs = append(allErrs, ValidateImmutableField(newMeta.Name, oldMeta.Name, fldPath.Child("name"))...)
|
allErrs = append(allErrs, ValidateImmutableField(newMeta.Name, oldMeta.Name, fldPath.Child("name"))...)
|
||||||
allErrs = append(allErrs, ValidateImmutableField(newMeta.Namespace, oldMeta.Namespace, fldPath.Child("namespace"))...)
|
allErrs = append(allErrs, ValidateImmutableField(newMeta.Namespace, oldMeta.Namespace, fldPath.Child("namespace"))...)
|
||||||
allErrs = append(allErrs, ValidateImmutableField(newMeta.UID, oldMeta.UID, fldPath.Child("uid"))...)
|
allErrs = append(allErrs, ValidateImmutableField(newMeta.UID, oldMeta.UID, fldPath.Child("uid"))...)
|
||||||
|
|
|
@ -330,6 +330,49 @@ func TestValidateObjectMetaUpdatePreventsDeletionFieldMutation(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestObjectMetaGenerationUpdate(t *testing.T) {
|
||||||
|
testcases := map[string]struct {
|
||||||
|
Old api.ObjectMeta
|
||||||
|
New api.ObjectMeta
|
||||||
|
ExpectedErrs []string
|
||||||
|
}{
|
||||||
|
"invalid generation change - decremented": {
|
||||||
|
Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 5},
|
||||||
|
New: api.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 4},
|
||||||
|
ExpectedErrs: []string{"field.generation: Invalid value: 4: must not be decremented"},
|
||||||
|
},
|
||||||
|
"valid generation change - incremented by one": {
|
||||||
|
Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 1},
|
||||||
|
New: api.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 2},
|
||||||
|
ExpectedErrs: []string{},
|
||||||
|
},
|
||||||
|
"valid generation field - not updated": {
|
||||||
|
Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 5},
|
||||||
|
New: api.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 5},
|
||||||
|
ExpectedErrs: []string{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, tc := range testcases {
|
||||||
|
errList := []string{}
|
||||||
|
errs := ValidateObjectMetaUpdate(&tc.New, &tc.Old, field.NewPath("field"))
|
||||||
|
if len(errs) != len(tc.ExpectedErrs) {
|
||||||
|
t.Logf("%s: Expected: %#v", k, tc.ExpectedErrs)
|
||||||
|
for _, err := range errs {
|
||||||
|
errList = append(errList, err.Error())
|
||||||
|
}
|
||||||
|
t.Logf("%s: Got: %#v", k, errList)
|
||||||
|
t.Errorf("%s: expected %d errors, got %d", k, len(tc.ExpectedErrs), len(errs))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for i := range errList {
|
||||||
|
if errList[i] != tc.ExpectedErrs[i] {
|
||||||
|
t.Errorf("%s: error #%d: expected %q, got %q", k, i, tc.ExpectedErrs[i], errList[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure trailing slash is allowed in generate name
|
// Ensure trailing slash is allowed in generate name
|
||||||
func TestValidateObjectMetaTrimsTrailingSlash(t *testing.T) {
|
func TestValidateObjectMetaTrimsTrailingSlash(t *testing.T) {
|
||||||
errs := ValidateObjectMeta(
|
errs := ValidateObjectMeta(
|
||||||
|
|
Loading…
Reference in New Issue