mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
dry-run: Add resttests
This commit is contained in:
parent
446eef54c5
commit
f3b8e85a4e
@ -1004,8 +1004,15 @@ func (e *Store) Delete(ctx context.Context, name string, options *metav1.DeleteO
|
|||||||
return out, false, err
|
return out, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If dry-run, then just return the object as just saved.
|
// Going further in this function is not useful when we are
|
||||||
if dryrun.IsDryRun(options.DryRun) {
|
// performing a dry-run request. Worse, it will actually
|
||||||
|
// override "out" with the version of the object in database
|
||||||
|
// that doesn't have the finalizer and deletiontimestamp set
|
||||||
|
// (because the update above was dry-run too). If we already
|
||||||
|
// have that version available, let's just return it now,
|
||||||
|
// otherwise, we can call dry-run delete that will get us the
|
||||||
|
// latest version of the object.
|
||||||
|
if dryrun.IsDryRun(options.DryRun) && out != nil {
|
||||||
return out, true, nil
|
return out, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,9 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO(apelisse): Tests in this file should be more hermertic by always
|
||||||
|
// removing objects that they create. That would avoid name-collisions.
|
||||||
|
|
||||||
type Tester struct {
|
type Tester struct {
|
||||||
*testing.T
|
*testing.T
|
||||||
storage rest.Storage
|
storage rest.Storage
|
||||||
@ -139,50 +142,74 @@ type UpdateFunc func(runtime.Object) runtime.Object
|
|||||||
|
|
||||||
// Test creating an object.
|
// Test creating an object.
|
||||||
func (t *Tester) TestCreate(valid runtime.Object, createFn CreateFunc, getFn GetFunc, invalid ...runtime.Object) {
|
func (t *Tester) TestCreate(valid runtime.Object, createFn CreateFunc, getFn GetFunc, invalid ...runtime.Object) {
|
||||||
|
dryRunOpts := metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}}
|
||||||
|
opts := metav1.CreateOptions{}
|
||||||
t.testCreateHasMetadata(valid.DeepCopyObject())
|
t.testCreateHasMetadata(valid.DeepCopyObject())
|
||||||
if !t.generatesName {
|
if !t.generatesName {
|
||||||
t.testCreateGeneratesName(valid.DeepCopyObject())
|
t.testCreateGeneratesName(valid.DeepCopyObject())
|
||||||
}
|
}
|
||||||
|
t.testCreateDryRun(valid.DeepCopyObject(), getFn)
|
||||||
|
t.testCreateDryRunEquals(valid.DeepCopyObject())
|
||||||
t.testCreateEquals(valid.DeepCopyObject(), getFn)
|
t.testCreateEquals(valid.DeepCopyObject(), getFn)
|
||||||
t.testCreateAlreadyExisting(valid.DeepCopyObject(), createFn)
|
t.testCreateAlreadyExisting(valid.DeepCopyObject(), createFn, dryRunOpts)
|
||||||
|
t.testCreateAlreadyExisting(valid.DeepCopyObject(), createFn, opts)
|
||||||
if t.clusterScope {
|
if t.clusterScope {
|
||||||
t.testCreateDiscardsObjectNamespace(valid.DeepCopyObject())
|
t.testCreateDiscardsObjectNamespace(valid.DeepCopyObject(), dryRunOpts)
|
||||||
t.testCreateIgnoresContextNamespace(valid.DeepCopyObject())
|
t.testCreateDiscardsObjectNamespace(valid.DeepCopyObject(), opts)
|
||||||
t.testCreateIgnoresMismatchedNamespace(valid.DeepCopyObject())
|
t.testCreateIgnoresContextNamespace(valid.DeepCopyObject(), dryRunOpts)
|
||||||
t.testCreateResetsUserData(valid.DeepCopyObject())
|
t.testCreateIgnoresContextNamespace(valid.DeepCopyObject(), opts)
|
||||||
|
t.testCreateIgnoresMismatchedNamespace(valid.DeepCopyObject(), dryRunOpts)
|
||||||
|
t.testCreateIgnoresMismatchedNamespace(valid.DeepCopyObject(), opts)
|
||||||
|
t.testCreateResetsUserData(valid.DeepCopyObject(), dryRunOpts)
|
||||||
|
t.testCreateResetsUserData(valid.DeepCopyObject(), opts)
|
||||||
} else {
|
} else {
|
||||||
t.testCreateRejectsMismatchedNamespace(valid.DeepCopyObject())
|
t.testCreateRejectsMismatchedNamespace(valid.DeepCopyObject(), dryRunOpts)
|
||||||
|
t.testCreateRejectsMismatchedNamespace(valid.DeepCopyObject(), opts)
|
||||||
}
|
}
|
||||||
t.testCreateInvokesValidation(invalid...)
|
t.testCreateInvokesValidation(dryRunOpts, invalid...)
|
||||||
t.testCreateValidatesNames(valid.DeepCopyObject())
|
t.testCreateInvokesValidation(opts, invalid...)
|
||||||
t.testCreateIgnoreClusterName(valid.DeepCopyObject())
|
t.testCreateValidatesNames(valid.DeepCopyObject(), dryRunOpts)
|
||||||
|
t.testCreateValidatesNames(valid.DeepCopyObject(), opts)
|
||||||
|
t.testCreateIgnoreClusterName(valid.DeepCopyObject(), dryRunOpts)
|
||||||
|
t.testCreateIgnoreClusterName(valid.DeepCopyObject(), opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test updating an object.
|
// Test updating an object.
|
||||||
func (t *Tester) TestUpdate(valid runtime.Object, createFn CreateFunc, getFn GetFunc, updateFn UpdateFunc, invalidUpdateFn ...UpdateFunc) {
|
func (t *Tester) TestUpdate(valid runtime.Object, createFn CreateFunc, getFn GetFunc, updateFn UpdateFunc, invalidUpdateFn ...UpdateFunc) {
|
||||||
|
dryRunOpts := metav1.UpdateOptions{DryRun: []string{metav1.DryRunAll}}
|
||||||
|
opts := metav1.UpdateOptions{}
|
||||||
t.testUpdateEquals(valid.DeepCopyObject(), createFn, getFn, updateFn)
|
t.testUpdateEquals(valid.DeepCopyObject(), createFn, getFn, updateFn)
|
||||||
t.testUpdateFailsOnVersionTooOld(valid.DeepCopyObject(), createFn, getFn)
|
t.testUpdateFailsOnVersionTooOld(valid.DeepCopyObject(), createFn, getFn)
|
||||||
t.testUpdateOnNotFound(valid.DeepCopyObject())
|
t.testUpdateOnNotFound(valid.DeepCopyObject(), dryRunOpts)
|
||||||
|
t.testUpdateOnNotFound(valid.DeepCopyObject(), opts)
|
||||||
if !t.clusterScope {
|
if !t.clusterScope {
|
||||||
t.testUpdateRejectsMismatchedNamespace(valid.DeepCopyObject(), createFn, getFn)
|
t.testUpdateRejectsMismatchedNamespace(valid.DeepCopyObject(), createFn, getFn)
|
||||||
}
|
}
|
||||||
t.testUpdateInvokesValidation(valid.DeepCopyObject(), createFn, invalidUpdateFn...)
|
t.testUpdateInvokesValidation(valid.DeepCopyObject(), createFn, invalidUpdateFn...)
|
||||||
t.testUpdateWithWrongUID(valid.DeepCopyObject(), createFn, getFn)
|
t.testUpdateWithWrongUID(valid.DeepCopyObject(), createFn, getFn, dryRunOpts)
|
||||||
|
t.testUpdateWithWrongUID(valid.DeepCopyObject(), createFn, getFn, opts)
|
||||||
t.testUpdateRetrievesOldObject(valid.DeepCopyObject(), createFn, getFn)
|
t.testUpdateRetrievesOldObject(valid.DeepCopyObject(), createFn, getFn)
|
||||||
t.testUpdatePropagatesUpdatedObjectError(valid.DeepCopyObject(), createFn, getFn)
|
t.testUpdatePropagatesUpdatedObjectError(valid.DeepCopyObject(), createFn, getFn, dryRunOpts)
|
||||||
|
t.testUpdatePropagatesUpdatedObjectError(valid.DeepCopyObject(), createFn, getFn, opts)
|
||||||
t.testUpdateIgnoreGenerationUpdates(valid.DeepCopyObject(), createFn, getFn)
|
t.testUpdateIgnoreGenerationUpdates(valid.DeepCopyObject(), createFn, getFn)
|
||||||
t.testUpdateIgnoreClusterName(valid.DeepCopyObject(), createFn, getFn)
|
t.testUpdateIgnoreClusterName(valid.DeepCopyObject(), createFn, getFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test deleting an object.
|
// Test deleting an object.
|
||||||
func (t *Tester) TestDelete(valid runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc) {
|
func (t *Tester) TestDelete(valid runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc) {
|
||||||
t.testDeleteNonExist(valid.DeepCopyObject())
|
dryRunOpts := metav1.DeleteOptions{DryRun: []string{metav1.DryRunAll}}
|
||||||
t.testDeleteNoGraceful(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn)
|
opts := metav1.DeleteOptions{}
|
||||||
t.testDeleteWithUID(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn)
|
t.testDeleteNonExist(valid.DeepCopyObject(), dryRunOpts)
|
||||||
|
t.testDeleteNonExist(valid.DeepCopyObject(), opts)
|
||||||
|
t.testDeleteNoGraceful(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn, true)
|
||||||
|
t.testDeleteNoGraceful(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn, false)
|
||||||
|
t.testDeleteWithUID(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn, dryRunOpts)
|
||||||
|
t.testDeleteWithUID(valid.DeepCopyObject(), createFn, getFn, isNotFoundFn, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test gracefully deleting an object.
|
// Test gracefully deleting an object.
|
||||||
func (t *Tester) TestDeleteGraceful(valid runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) {
|
func (t *Tester) TestDeleteGraceful(valid runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) {
|
||||||
|
t.testDeleteDryRunGracefulHasdefault(valid.DeepCopyObject(), createFn, expectedGrace)
|
||||||
t.testDeleteGracefulHasDefault(valid.DeepCopyObject(), createFn, getFn, expectedGrace)
|
t.testDeleteGracefulHasDefault(valid.DeepCopyObject(), createFn, getFn, expectedGrace)
|
||||||
t.testDeleteGracefulWithValue(valid.DeepCopyObject(), createFn, getFn, expectedGrace)
|
t.testDeleteGracefulWithValue(valid.DeepCopyObject(), createFn, getFn, expectedGrace)
|
||||||
t.testDeleteGracefulUsesZeroOnNil(valid.DeepCopyObject(), createFn, expectedGrace)
|
t.testDeleteGracefulUsesZeroOnNil(valid.DeepCopyObject(), createFn, expectedGrace)
|
||||||
@ -233,7 +260,7 @@ func (t *Tester) delete(ctx context.Context, obj runtime.Object) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testCreateAlreadyExisting(obj runtime.Object, createFn CreateFunc) {
|
func (t *Tester) testCreateAlreadyExisting(obj runtime.Object, createFn CreateFunc, opts metav1.CreateOptions) {
|
||||||
ctx := t.TestContext()
|
ctx := t.TestContext()
|
||||||
|
|
||||||
foo := obj.DeepCopyObject()
|
foo := obj.DeepCopyObject()
|
||||||
@ -243,12 +270,59 @@ func (t *Tester) testCreateAlreadyExisting(obj runtime.Object, createFn CreateFu
|
|||||||
}
|
}
|
||||||
defer t.delete(ctx, foo)
|
defer t.delete(ctx, foo)
|
||||||
|
|
||||||
_, err := t.storage.(rest.Creater).Create(ctx, foo, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
_, err := t.storage.(rest.Creater).Create(ctx, foo, rest.ValidateAllObjectFunc, &opts)
|
||||||
if !errors.IsAlreadyExists(err) {
|
if !errors.IsAlreadyExists(err) {
|
||||||
t.Errorf("expected already exists err, got %v", err)
|
t.Errorf("expected already exists err, got %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tester) testCreateDryRun(obj runtime.Object, getFn GetFunc) {
|
||||||
|
ctx := t.TestContext()
|
||||||
|
|
||||||
|
foo := obj.DeepCopyObject()
|
||||||
|
t.setObjectMeta(foo, t.namer(2))
|
||||||
|
|
||||||
|
_, err := t.storage.(rest.Creater).Create(ctx, foo, rest.ValidateAllObjectFunc, &metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = getFn(ctx, foo)
|
||||||
|
if !errors.IsNotFound(err) {
|
||||||
|
t.Errorf("Expected NotFound error, got '%v'", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tester) testCreateDryRunEquals(obj runtime.Object) {
|
||||||
|
ctx := t.TestContext()
|
||||||
|
|
||||||
|
foo := obj.DeepCopyObject()
|
||||||
|
t.setObjectMeta(foo, t.namer(2))
|
||||||
|
|
||||||
|
createdFake, err := t.storage.(rest.Creater).Create(ctx, foo, rest.ValidateAllObjectFunc, &metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
created, err := t.storage.(rest.Creater).Create(ctx, foo, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
defer t.delete(ctx, created)
|
||||||
|
|
||||||
|
// Set resource version which might be unset in created object.
|
||||||
|
createdMeta := t.getObjectMetaOrFail(created)
|
||||||
|
createdFakeMeta := t.getObjectMetaOrFail(createdFake)
|
||||||
|
createdMeta.SetCreationTimestamp(createdFakeMeta.GetCreationTimestamp())
|
||||||
|
createdFakeMeta.SetResourceVersion("")
|
||||||
|
createdMeta.SetResourceVersion("")
|
||||||
|
createdMeta.SetUID(createdFakeMeta.GetUID())
|
||||||
|
|
||||||
|
if e, a := created, createdFake; !apiequality.Semantic.DeepEqual(e, a) {
|
||||||
|
t.Errorf("unexpected obj: %#v, expected %#v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tester) testCreateEquals(obj runtime.Object, getFn GetFunc) {
|
func (t *Tester) testCreateEquals(obj runtime.Object, getFn GetFunc) {
|
||||||
ctx := t.TestContext()
|
ctx := t.TestContext()
|
||||||
|
|
||||||
@ -276,14 +350,14 @@ func (t *Tester) testCreateEquals(obj runtime.Object, getFn GetFunc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testCreateDiscardsObjectNamespace(valid runtime.Object) {
|
func (t *Tester) testCreateDiscardsObjectNamespace(valid runtime.Object, opts metav1.CreateOptions) {
|
||||||
objectMeta := t.getObjectMetaOrFail(valid)
|
objectMeta := t.getObjectMetaOrFail(valid)
|
||||||
|
|
||||||
// Ignore non-empty namespace in object meta
|
// Ignore non-empty namespace in object meta
|
||||||
objectMeta.SetNamespace("not-default")
|
objectMeta.SetNamespace("not-default")
|
||||||
|
|
||||||
// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
|
// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
|
||||||
created, err := t.storage.(rest.Creater).Create(t.TestContext(), valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
created, err := t.storage.(rest.Creater).Create(t.TestContext(), valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -327,12 +401,12 @@ func (t *Tester) testCreateHasMetadata(valid runtime.Object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testCreateIgnoresContextNamespace(valid runtime.Object) {
|
func (t *Tester) testCreateIgnoresContextNamespace(valid runtime.Object, opts metav1.CreateOptions) {
|
||||||
// Ignore non-empty namespace in context
|
// Ignore non-empty namespace in context
|
||||||
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "not-default2")
|
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "not-default2")
|
||||||
|
|
||||||
// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
|
// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
|
||||||
created, err := t.storage.(rest.Creater).Create(ctx, valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
created, err := t.storage.(rest.Creater).Create(ctx, valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -343,7 +417,7 @@ func (t *Tester) testCreateIgnoresContextNamespace(valid runtime.Object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testCreateIgnoresMismatchedNamespace(valid runtime.Object) {
|
func (t *Tester) testCreateIgnoresMismatchedNamespace(valid runtime.Object, opts metav1.CreateOptions) {
|
||||||
objectMeta := t.getObjectMetaOrFail(valid)
|
objectMeta := t.getObjectMetaOrFail(valid)
|
||||||
|
|
||||||
// Ignore non-empty namespace in object meta
|
// Ignore non-empty namespace in object meta
|
||||||
@ -351,7 +425,7 @@ func (t *Tester) testCreateIgnoresMismatchedNamespace(valid runtime.Object) {
|
|||||||
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "not-default2")
|
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "not-default2")
|
||||||
|
|
||||||
// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
|
// Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted
|
||||||
created, err := t.storage.(rest.Creater).Create(ctx, valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
created, err := t.storage.(rest.Creater).Create(ctx, valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -362,14 +436,14 @@ func (t *Tester) testCreateIgnoresMismatchedNamespace(valid runtime.Object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testCreateValidatesNames(valid runtime.Object) {
|
func (t *Tester) testCreateValidatesNames(valid runtime.Object, opts metav1.CreateOptions) {
|
||||||
for _, invalidName := range path.NameMayNotBe {
|
for _, invalidName := range path.NameMayNotBe {
|
||||||
objCopy := valid.DeepCopyObject()
|
objCopy := valid.DeepCopyObject()
|
||||||
objCopyMeta := t.getObjectMetaOrFail(objCopy)
|
objCopyMeta := t.getObjectMetaOrFail(objCopy)
|
||||||
objCopyMeta.SetName(invalidName)
|
objCopyMeta.SetName(invalidName)
|
||||||
|
|
||||||
ctx := t.TestContext()
|
ctx := t.TestContext()
|
||||||
_, err := t.storage.(rest.Creater).Create(ctx, objCopy, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
_, err := t.storage.(rest.Creater).Create(ctx, objCopy, rest.ValidateAllObjectFunc, &opts)
|
||||||
if !errors.IsInvalid(err) {
|
if !errors.IsInvalid(err) {
|
||||||
t.Errorf("%s: Expected to get an invalid resource error, got '%v'", invalidName, err)
|
t.Errorf("%s: Expected to get an invalid resource error, got '%v'", invalidName, err)
|
||||||
}
|
}
|
||||||
@ -381,24 +455,24 @@ func (t *Tester) testCreateValidatesNames(valid runtime.Object) {
|
|||||||
objCopyMeta.SetName(objCopyMeta.GetName() + invalidSuffix)
|
objCopyMeta.SetName(objCopyMeta.GetName() + invalidSuffix)
|
||||||
|
|
||||||
ctx := t.TestContext()
|
ctx := t.TestContext()
|
||||||
_, err := t.storage.(rest.Creater).Create(ctx, objCopy, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
_, err := t.storage.(rest.Creater).Create(ctx, objCopy, rest.ValidateAllObjectFunc, &opts)
|
||||||
if !errors.IsInvalid(err) {
|
if !errors.IsInvalid(err) {
|
||||||
t.Errorf("%s: Expected to get an invalid resource error, got '%v'", invalidSuffix, err)
|
t.Errorf("%s: Expected to get an invalid resource error, got '%v'", invalidSuffix, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testCreateInvokesValidation(invalid ...runtime.Object) {
|
func (t *Tester) testCreateInvokesValidation(opts metav1.CreateOptions, invalid ...runtime.Object) {
|
||||||
for i, obj := range invalid {
|
for i, obj := range invalid {
|
||||||
ctx := t.TestContext()
|
ctx := t.TestContext()
|
||||||
_, err := t.storage.(rest.Creater).Create(ctx, obj, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
_, err := t.storage.(rest.Creater).Create(ctx, obj, rest.ValidateAllObjectFunc, &opts)
|
||||||
if !errors.IsInvalid(err) {
|
if !errors.IsInvalid(err) {
|
||||||
t.Errorf("%d: Expected to get an invalid resource error, got %v", i, err)
|
t.Errorf("%d: Expected to get an invalid resource error, got %v", i, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testCreateRejectsMismatchedNamespace(valid runtime.Object) {
|
func (t *Tester) testCreateRejectsMismatchedNamespace(valid runtime.Object, opts metav1.CreateOptions) {
|
||||||
objectMeta := t.getObjectMetaOrFail(valid)
|
objectMeta := t.getObjectMetaOrFail(valid)
|
||||||
objectMeta.SetNamespace("not-default")
|
objectMeta.SetNamespace("not-default")
|
||||||
|
|
||||||
@ -410,13 +484,13 @@ func (t *Tester) testCreateRejectsMismatchedNamespace(valid runtime.Object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testCreateResetsUserData(valid runtime.Object) {
|
func (t *Tester) testCreateResetsUserData(valid runtime.Object, opts metav1.CreateOptions) {
|
||||||
objectMeta := t.getObjectMetaOrFail(valid)
|
objectMeta := t.getObjectMetaOrFail(valid)
|
||||||
now := metav1.Now()
|
now := metav1.Now()
|
||||||
objectMeta.SetUID("bad-uid")
|
objectMeta.SetUID("bad-uid")
|
||||||
objectMeta.SetCreationTimestamp(now)
|
objectMeta.SetCreationTimestamp(now)
|
||||||
|
|
||||||
obj, err := t.storage.(rest.Creater).Create(t.TestContext(), valid, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
obj, err := t.storage.(rest.Creater).Create(t.TestContext(), valid, rest.ValidateAllObjectFunc, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -429,12 +503,12 @@ func (t *Tester) testCreateResetsUserData(valid runtime.Object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testCreateIgnoreClusterName(valid runtime.Object) {
|
func (t *Tester) testCreateIgnoreClusterName(valid runtime.Object, opts metav1.CreateOptions) {
|
||||||
objectMeta := t.getObjectMetaOrFail(valid)
|
objectMeta := t.getObjectMetaOrFail(valid)
|
||||||
objectMeta.SetName(t.namer(3))
|
objectMeta.SetName(t.namer(3))
|
||||||
objectMeta.SetClusterName("clustername-to-ignore")
|
objectMeta.SetClusterName("clustername-to-ignore")
|
||||||
|
|
||||||
obj, err := t.storage.(rest.Creater).Create(t.TestContext(), valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
obj, err := t.storage.(rest.Creater).Create(t.TestContext(), valid.DeepCopyObject(), rest.ValidateAllObjectFunc, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -533,7 +607,7 @@ func (t *Tester) testUpdateInvokesValidation(obj runtime.Object, createFn Create
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testUpdateWithWrongUID(obj runtime.Object, createFn CreateFunc, getFn GetFunc) {
|
func (t *Tester) testUpdateWithWrongUID(obj runtime.Object, createFn CreateFunc, getFn GetFunc, opts metav1.UpdateOptions) {
|
||||||
ctx := t.TestContext()
|
ctx := t.TestContext()
|
||||||
foo := obj.DeepCopyObject()
|
foo := obj.DeepCopyObject()
|
||||||
t.setObjectMeta(foo, t.namer(5))
|
t.setObjectMeta(foo, t.namer(5))
|
||||||
@ -542,9 +616,10 @@ func (t *Tester) testUpdateWithWrongUID(obj runtime.Object, createFn CreateFunc,
|
|||||||
if err := createFn(ctx, foo); err != nil {
|
if err := createFn(ctx, foo); err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
defer t.delete(ctx, foo)
|
||||||
objectMeta.SetUID(types.UID("UID1111"))
|
objectMeta.SetUID(types.UID("UID1111"))
|
||||||
|
|
||||||
obj, created, err := t.storage.(rest.Updater).Update(ctx, objectMeta.GetName(), rest.DefaultUpdatedObjectInfo(foo), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
|
obj, created, err := t.storage.(rest.Updater).Update(ctx, objectMeta.GetName(), rest.DefaultUpdatedObjectInfo(foo), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &opts)
|
||||||
if created || obj != nil {
|
if created || obj != nil {
|
||||||
t.Errorf("expected nil object and no creation for object: %v", foo)
|
t.Errorf("expected nil object and no creation for object: %v", foo)
|
||||||
}
|
}
|
||||||
@ -607,7 +682,7 @@ func (t *Tester) testUpdateRetrievesOldObject(obj runtime.Object, createFn Creat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testUpdatePropagatesUpdatedObjectError(obj runtime.Object, createFn CreateFunc, getFn GetFunc) {
|
func (t *Tester) testUpdatePropagatesUpdatedObjectError(obj runtime.Object, createFn CreateFunc, getFn GetFunc, opts metav1.UpdateOptions) {
|
||||||
ctx := t.TestContext()
|
ctx := t.TestContext()
|
||||||
foo := obj.DeepCopyObject()
|
foo := obj.DeepCopyObject()
|
||||||
name := t.namer(7)
|
name := t.namer(7)
|
||||||
@ -616,6 +691,7 @@ func (t *Tester) testUpdatePropagatesUpdatedObjectError(obj runtime.Object, crea
|
|||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer t.delete(ctx, foo)
|
||||||
|
|
||||||
// Make sure our transform is called, and sees the expected updatedObject and oldObject
|
// Make sure our transform is called, and sees the expected updatedObject and oldObject
|
||||||
propagateErr := fmt.Errorf("custom updated object error for %v", foo)
|
propagateErr := fmt.Errorf("custom updated object error for %v", foo)
|
||||||
@ -623,7 +699,7 @@ func (t *Tester) testUpdatePropagatesUpdatedObjectError(obj runtime.Object, crea
|
|||||||
return nil, propagateErr
|
return nil, propagateErr
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, err := t.storage.(rest.Updater).Update(ctx, name, rest.DefaultUpdatedObjectInfo(foo, noopTransform), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
|
_, _, err := t.storage.(rest.Updater).Update(ctx, name, rest.DefaultUpdatedObjectInfo(foo, noopTransform), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &opts)
|
||||||
if err != propagateErr {
|
if err != propagateErr {
|
||||||
t.Errorf("expected propagated error, got %#v", err)
|
t.Errorf("expected propagated error, got %#v", err)
|
||||||
}
|
}
|
||||||
@ -663,9 +739,9 @@ func (t *Tester) testUpdateIgnoreGenerationUpdates(obj runtime.Object, createFn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testUpdateOnNotFound(obj runtime.Object) {
|
func (t *Tester) testUpdateOnNotFound(obj runtime.Object, opts metav1.UpdateOptions) {
|
||||||
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), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
|
_, created, err := t.storage.(rest.Updater).Update(t.TestContext(), t.namer(0), rest.DefaultUpdatedObjectInfo(obj), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &opts)
|
||||||
if t.createOnUpdate {
|
if t.createOnUpdate {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("creation allowed on updated, but got an error: %v", err)
|
t.Errorf("creation allowed on updated, but got an error: %v", err)
|
||||||
@ -749,7 +825,7 @@ func (t *Tester) testUpdateIgnoreClusterName(obj runtime.Object, createFn Create
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Deletion tests.
|
// Deletion tests.
|
||||||
|
|
||||||
func (t *Tester) testDeleteNoGraceful(obj runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc) {
|
func (t *Tester) testDeleteNoGraceful(obj runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc, dryRun bool) {
|
||||||
ctx := t.TestContext()
|
ctx := t.TestContext()
|
||||||
|
|
||||||
foo := obj.DeepCopyObject()
|
foo := obj.DeepCopyObject()
|
||||||
@ -757,8 +833,13 @@ func (t *Tester) testDeleteNoGraceful(obj runtime.Object, createFn CreateFunc, g
|
|||||||
if err := createFn(ctx, foo); err != nil {
|
if err := createFn(ctx, foo); err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
defer t.delete(ctx, foo)
|
||||||
objectMeta := t.getObjectMetaOrFail(foo)
|
objectMeta := t.getObjectMetaOrFail(foo)
|
||||||
obj, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), metav1.NewDeleteOptions(10))
|
opts := metav1.NewDeleteOptions(10)
|
||||||
|
if dryRun {
|
||||||
|
opts.DryRun = []string{metav1.DryRunAll}
|
||||||
|
}
|
||||||
|
obj, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -774,15 +855,17 @@ func (t *Tester) testDeleteNoGraceful(obj runtime.Object, createFn CreateFunc, g
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err = getFn(ctx, foo)
|
_, err = getFn(ctx, foo)
|
||||||
if err == nil || !isNotFoundFn(err) {
|
if !dryRun && (err == nil || !isNotFoundFn(err)) {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
} else if dryRun && isNotFoundFn(err) {
|
||||||
|
t.Error("object should not have been removed in dry-run")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tester) testDeleteNonExist(obj runtime.Object) {
|
func (t *Tester) testDeleteNonExist(obj runtime.Object, opts metav1.DeleteOptions) {
|
||||||
objectMeta := t.getObjectMetaOrFail(obj)
|
objectMeta := t.getObjectMetaOrFail(obj)
|
||||||
|
|
||||||
_, _, err := t.storage.(rest.GracefulDeleter).Delete(t.TestContext(), objectMeta.GetName(), nil)
|
_, _, err := t.storage.(rest.GracefulDeleter).Delete(t.TestContext(), objectMeta.GetName(), &opts)
|
||||||
if err == nil || !errors.IsNotFound(err) {
|
if err == nil || !errors.IsNotFound(err) {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -791,7 +874,7 @@ func (t *Tester) testDeleteNonExist(obj runtime.Object) {
|
|||||||
|
|
||||||
// This test the fast-fail path. We test that the precondition gets verified
|
// This test the fast-fail path. We test that the precondition gets verified
|
||||||
// again before deleting the object in tests of pkg/storage/etcd.
|
// again before deleting the object in tests of pkg/storage/etcd.
|
||||||
func (t *Tester) testDeleteWithUID(obj runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc) {
|
func (t *Tester) testDeleteWithUID(obj runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc, opts metav1.DeleteOptions) {
|
||||||
ctx := t.TestContext()
|
ctx := t.TestContext()
|
||||||
|
|
||||||
foo := obj.DeepCopyObject()
|
foo := obj.DeepCopyObject()
|
||||||
@ -801,7 +884,8 @@ func (t *Tester) testDeleteWithUID(obj runtime.Object, createFn CreateFunc, getF
|
|||||||
if err := createFn(ctx, foo); err != nil {
|
if err := createFn(ctx, foo); err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
obj, _, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), metav1.NewPreconditionDeleteOptions("UID1111"))
|
opts.Preconditions = metav1.NewPreconditionDeleteOptions("UID1111").Preconditions
|
||||||
|
obj, _, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), &opts)
|
||||||
if err == nil || !errors.IsConflict(err) {
|
if err == nil || !errors.IsConflict(err) {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -828,6 +912,33 @@ func (t *Tester) testDeleteWithUID(obj runtime.Object, createFn CreateFunc, getF
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Graceful Deletion tests.
|
// Graceful Deletion tests.
|
||||||
|
|
||||||
|
func (t *Tester) testDeleteDryRunGracefulHasdefault(obj runtime.Object, createFn CreateFunc, expectedGrace int64) {
|
||||||
|
ctx := t.TestContext()
|
||||||
|
|
||||||
|
foo := obj.DeepCopyObject()
|
||||||
|
t.setObjectMeta(foo, t.namer(1))
|
||||||
|
defer t.delete(ctx, foo)
|
||||||
|
if err := createFn(ctx, foo); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
objectMeta := t.getObjectMetaOrFail(foo)
|
||||||
|
object, wasDeleted, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), &metav1.DeleteOptions{DryRun: []string{metav1.DryRunAll}})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if wasDeleted {
|
||||||
|
t.Errorf("unexpected, object %s should not have been deleted immediately", objectMeta.GetName())
|
||||||
|
}
|
||||||
|
objectMeta = t.getObjectMetaOrFail(object)
|
||||||
|
if objectMeta.GetDeletionTimestamp() == nil || objectMeta.GetDeletionGracePeriodSeconds() == nil || *objectMeta.GetDeletionGracePeriodSeconds() != expectedGrace {
|
||||||
|
t.Errorf("unexpected deleted meta: %#v", objectMeta)
|
||||||
|
}
|
||||||
|
_, _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.GetName(), &metav1.DeleteOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tester) testDeleteGracefulHasDefault(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) {
|
func (t *Tester) testDeleteGracefulHasDefault(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) {
|
||||||
ctx := t.TestContext()
|
ctx := t.TestContext()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user