func TestStoreDelete(t *testing.T) { podA := &api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Spec: api.PodSpec{NodeName: "machine"}, } testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") destroyFunc, registry := NewTestGenericStoreRegistry(t) defer destroyFunc() // test failure condition _, err := registry.Delete(testContext, podA.Name, nil) if !errors.IsNotFound(err) { t.Errorf("Unexpected error: %v", err) } // create pod _, err = registry.Create(testContext, podA) if err != nil { t.Errorf("Unexpected error: %v", err) } // delete object _, err = registry.Delete(testContext, podA.Name, nil) if err != nil { t.Errorf("Unexpected error: %v", err) } // try to get a item which should be deleted _, err = registry.Get(testContext, podA.Name, &metav1.GetOptions{}) if !errors.IsNotFound(err) { t.Errorf("Unexpected error: %v", err) } }
// TestGracefulStoreCanDeleteIfExistingGracePeriodZero tests recovery from // race condition where the graceful delete is unable to complete // in prior operation, but the pod remains with deletion timestamp // and grace period set to 0. func TestGracefulStoreCanDeleteIfExistingGracePeriodZero(t *testing.T) { deletionTimestamp := metav1.NewTime(time.Now()) deletionGracePeriodSeconds := int64(0) initialGeneration := int64(1) pod := &api.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", Generation: initialGeneration, DeletionGracePeriodSeconds: &deletionGracePeriodSeconds, DeletionTimestamp: &deletionTimestamp, }, Spec: api.PodSpec{NodeName: "machine"}, } testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") destroyFunc, registry := NewTestGenericStoreRegistry(t) registry.EnableGarbageCollection = false defaultDeleteStrategy := testRESTStrategy{api.Scheme, names.SimpleNameGenerator, true, false, true} registry.DeleteStrategy = testGracefulStrategy{defaultDeleteStrategy} defer destroyFunc() graceful, gracefulPending, err := rest.BeforeDelete(registry.DeleteStrategy, testContext, pod, api.NewDeleteOptions(0)) if err != nil { t.Fatalf("Unexpected error: %v", err) } if graceful { t.Fatalf("graceful should be false if object has DeletionTimestamp and DeletionGracePeriodSeconds is 0") } if gracefulPending { t.Fatalf("gracefulPending should be false if object has DeletionTimestamp and DeletionGracePeriodSeconds is 0") } }
func TestStoreBasicExport(t *testing.T) { podA := api.Pod{ ObjectMeta: metav1.ObjectMeta{ Namespace: "test", Name: "foo", Labels: map[string]string{}, }, Spec: api.PodSpec{NodeName: "machine"}, Status: api.PodStatus{HostIP: "1.2.3.4"}, } destroyFunc, registry := NewTestGenericStoreRegistry(t) defer destroyFunc() testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true if !updateAndVerify(t, testContext, registry, &podA) { t.Errorf("Unexpected error updating podA") } obj, err := registry.Export(testContext, podA.Name, metav1.ExportOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) } exportedPod := obj.(*api.Pod) if exportedPod.Labels["prepare_create"] != "true" { t.Errorf("expected: prepare_create->true, found: %s", exportedPod.Labels["prepare_create"]) } delete(exportedPod.Labels, "prepare_create") exportObjectMeta(&podA.ObjectMeta, false) podA.Spec = exportedPod.Spec if !reflect.DeepEqual(&podA, exportedPod) { t.Errorf("expected:\n%v\nsaw:\n%v\n", &podA, exportedPod) } }
func TestUpdate(t *testing.T) { storage, _, si, destroyFunc := newStorage(t) defer destroyFunc() ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") key := "/controllers/test/foo" if err := si.Create(ctx, key, &validController, nil, 0); err != nil { t.Fatalf("unexpected error: %v", err) } replicas := int32(12) update := extensions.Scale{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test"}, Spec: extensions.ScaleSpec{ Replicas: replicas, }, } if _, _, err := storage.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update, api.Scheme)); err != nil { t.Fatalf("unexpected error: %v", err) } obj, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } updated := obj.(*extensions.Scale) if updated.Spec.Replicas != replicas { t.Errorf("wrong replicas count expected: %d got: %d", replicas, updated.Spec.Replicas) } }
func TestStoreDeleteCollection(t *testing.T) { podA := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} podB := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}} testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") destroyFunc, registry := NewTestGenericStoreRegistry(t) defer destroyFunc() if _, err := registry.Create(testContext, podA); err != nil { t.Errorf("Unexpected error: %v", err) } if _, err := registry.Create(testContext, podB); err != nil { t.Errorf("Unexpected error: %v", err) } // Delete all pods. deleted, err := registry.DeleteCollection(testContext, nil, &api.ListOptions{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } deletedPods := deleted.(*api.PodList) if len(deletedPods.Items) != 2 { t.Errorf("Unexpected number of pods deleted: %d, expected: 2", len(deletedPods.Items)) } if _, err := registry.Get(testContext, podA.Name, &metav1.GetOptions{}); !errors.IsNotFound(err) { t.Errorf("Unexpected error: %v", err) } if _, err := registry.Get(testContext, podB.Name, &metav1.GetOptions{}); !errors.IsNotFound(err) { t.Errorf("Unexpected error: %v", err) } }
func TestStatusUpdate(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) defer storage.Deployment.Store.DestroyFunc() ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace) key := "/deployments/" + namespace + "/" + name if err := storage.Deployment.Storage.Create(ctx, key, &validDeployment, nil, 0); err != nil { t.Fatalf("unexpected error: %v", err) } update := extensions.Deployment{ ObjectMeta: validDeployment.ObjectMeta, Spec: extensions.DeploymentSpec{ Replicas: defaultReplicas, }, Status: extensions.DeploymentStatus{ Replicas: defaultReplicas, }, } if _, _, err := storage.Status.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update, api.Scheme)); err != nil { t.Fatalf("unexpected error: %v", err) } obj, err := storage.Deployment.Get(ctx, name, &metav1.GetOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } deployment := obj.(*extensions.Deployment) if deployment.Spec.Replicas != 7 { t.Errorf("we expected .spec.replicas to not be updated but it was updated to %v", deployment.Spec.Replicas) } if deployment.Status.Replicas != defaultReplicas { t.Errorf("we expected .status.replicas to be updated to %d but it was %v", defaultReplicas, deployment.Status.Replicas) } }
// Ensure that when a deploymentRollback is created for a deployment that has already been deleted // by the API server, API server returns not-found error. func TestEtcdCreateDeploymentRollbackNoDeployment(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) defer storage.Deployment.Store.DestroyFunc() rollbackStorage := storage.Rollback ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace) _, err := rollbackStorage.Create(ctx, &extensions.DeploymentRollback{ Name: name, UpdatedAnnotations: map[string]string{}, RollbackTo: extensions.RollbackConfig{Revision: 1}, }) if err == nil { t.Fatalf("Expected not-found-error but got nothing") } if !errors.IsNotFound(storeerr.InterpretGetError(err, extensions.Resource("deployments"), name)) { t.Fatalf("Unexpected error returned: %#v", err) } _, err = storage.Deployment.Get(ctx, name, &metav1.GetOptions{}) if err == nil { t.Fatalf("Expected not-found-error but got nothing") } if !errors.IsNotFound(storeerr.InterpretGetError(err, extensions.Resource("deployments"), name)) { t.Fatalf("Unexpected error: %v", err) } }
// Bind just does a POST binding RPC. func (b *binder) Bind(binding *v1.Binding) error { glog.V(3).Infof("Attempting to bind %v to %v", binding.Name, binding.Target.Name) ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), binding.Namespace) return b.Client.Core().RESTClient().Post().Namespace(genericapirequest.NamespaceValue(ctx)).Resource("bindings").Body(binding).Do().Error() // TODO: use Pods interface for binding once clusters are upgraded // return b.Pods(binding.Namespace).Bind(binding) }
// testGetDifferentNamespace ensures same-name objects in different namespaces do not clash func (t *Tester) testGetDifferentNamespace(obj runtime.Object) { if t.clusterScope { t.Fatalf("the test does not work in in cluster-scope") } objMeta := t.getObjectMetaOrFail(obj) objMeta.Name = t.namer(5) ctx1 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar3") objMeta.Namespace = genericapirequest.NamespaceValue(ctx1) _, err := t.storage.(rest.Creater).Create(ctx1, obj) if err != nil { t.Errorf("unexpected error: %v", err) } ctx2 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar4") objMeta.Namespace = genericapirequest.NamespaceValue(ctx2) _, err = t.storage.(rest.Creater).Create(ctx2, obj) if err != nil { t.Errorf("unexpected error: %v", err) } got1, err := t.storage.(rest.Getter).Get(ctx1, objMeta.Name, &metav1.GetOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) } got1Meta := t.getObjectMetaOrFail(got1) if got1Meta.Name != objMeta.Name { t.Errorf("unexpected name of object: %#v, expected: %s", got1, objMeta.Name) } if got1Meta.Namespace != genericapirequest.NamespaceValue(ctx1) { t.Errorf("unexpected namespace of object: %#v, expected: %s", got1, genericapirequest.NamespaceValue(ctx1)) } got2, err := t.storage.(rest.Getter).Get(ctx2, objMeta.Name, &metav1.GetOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) } got2Meta := t.getObjectMetaOrFail(got2) if got2Meta.Name != objMeta.Name { t.Errorf("unexpected name of object: %#v, expected: %s", got2, objMeta.Name) } if got2Meta.Namespace != genericapirequest.NamespaceValue(ctx2) { t.Errorf("unexpected namespace of object: %#v, expected: %s", got2, genericapirequest.NamespaceValue(ctx2)) } }
func TestGracefulStoreHandleFinalizers(t *testing.T) { initialGeneration := int64(1) podWithFinalizer := &api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Finalizers: []string{"foo.com/x"}, Generation: initialGeneration}, Spec: api.PodSpec{NodeName: "machine"}, } testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") destroyFunc, registry := NewTestGenericStoreRegistry(t) registry.EnableGarbageCollection = true defaultDeleteStrategy := testRESTStrategy{api.Scheme, names.SimpleNameGenerator, true, false, true} registry.DeleteStrategy = testGracefulStrategy{defaultDeleteStrategy} defer destroyFunc() // create pod _, err := registry.Create(testContext, podWithFinalizer) if err != nil { t.Errorf("Unexpected error: %v", err) } // delete the pod with grace period=0, the pod should still exist because it has a finalizer _, err = registry.Delete(testContext, podWithFinalizer.Name, api.NewDeleteOptions(0)) if err != nil { t.Fatalf("Unexpected error: %v", err) } _, err = registry.Get(testContext, podWithFinalizer.Name, &metav1.GetOptions{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } updatedPodWithFinalizer := &api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Finalizers: []string{"foo.com/x"}, ResourceVersion: podWithFinalizer.ObjectMeta.ResourceVersion}, Spec: api.PodSpec{NodeName: "machine"}, } _, _, err = registry.Update(testContext, updatedPodWithFinalizer.ObjectMeta.Name, rest.DefaultUpdatedObjectInfo(updatedPodWithFinalizer, api.Scheme)) if err != nil { t.Fatalf("Unexpected error: %v", err) } // the object should still exist, because it still has a finalizer _, err = registry.Get(testContext, podWithFinalizer.Name, &metav1.GetOptions{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } podWithNoFinalizer := &api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: podWithFinalizer.ObjectMeta.ResourceVersion}, Spec: api.PodSpec{NodeName: "anothermachine"}, } _, _, err = registry.Update(testContext, podWithFinalizer.ObjectMeta.Name, rest.DefaultUpdatedObjectInfo(podWithNoFinalizer, api.Scheme)) if err != nil { t.Fatalf("Unexpected error: %v", err) } // the pod should be removed, because its finalizer is removed _, err = registry.Get(testContext, podWithFinalizer.Name, &metav1.GetOptions{}) if !errors.IsNotFound(err) { t.Fatalf("Unexpected error: %v", err) } }
// createNetworkPolicy is a helper function that returns a NetworkPolicy with the updated resource version. func createNetworkPolicy(storage *REST, np extensions.NetworkPolicy, t *testing.T) (extensions.NetworkPolicy, error) { ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), np.Namespace) obj, err := storage.Create(ctx, &np) if err != nil { t.Errorf("Failed to create NetworkPolicy, %v", err) } newNP := obj.(*extensions.NetworkPolicy) return *newNP, nil }
// createReplicaSet is a helper function that returns a ReplicaSet with the updated resource version. func createReplicaSet(storage *REST, rs extensions.ReplicaSet, t *testing.T) (extensions.ReplicaSet, error) { ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), rs.Namespace) obj, err := storage.Create(ctx, &rs) if err != nil { t.Errorf("Failed to create ReplicaSet, %v", err) } newRS := obj.(*extensions.ReplicaSet) return *newRS, nil }
// createController is a helper function that returns a controller with the updated resource version. func createController(storage *REST, rc api.ReplicationController, t *testing.T) (api.ReplicationController, error) { ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), rc.Namespace) obj, err := storage.Create(ctx, &rc) if err != nil { t.Errorf("Failed to create controller, %v", err) } newRc := obj.(*api.ReplicationController) return *newRc, nil }
// createPodDisruptionBudget is a helper function that returns a PodDisruptionBudget with the updated resource version. func createPodDisruptionBudget(storage *REST, pdb policy.PodDisruptionBudget, t *testing.T) (policy.PodDisruptionBudget, error) { ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), pdb.Namespace) obj, err := storage.Create(ctx, &pdb) if err != nil { t.Errorf("Failed to create PodDisruptionBudget, %v", err) } newPS := obj.(*policy.PodDisruptionBudget) return *newPS, nil }
// createStatefulSet is a helper function that returns a StatefulSet with the updated resource version. func createStatefulSet(storage *REST, ps apps.StatefulSet, t *testing.T) (apps.StatefulSet, error) { ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), ps.Namespace) obj, err := storage.Create(ctx, &ps) if err != nil { t.Errorf("Failed to create StatefulSet, %v", err) } newPS := obj.(*apps.StatefulSet) return *newPS, nil }
func (r *registryGetter) GetSecret(namespace, name string) (*v1.Secret, error) { ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace) internalSecret, err := r.secrets.GetSecret(ctx, name, &metav1.GetOptions{}) if err != nil { return nil, err } v1Secret := v1.Secret{} err = v1.Convert_api_Secret_To_v1_Secret(internalSecret, &v1Secret, nil) return &v1Secret, err }
func TestStoreWatch(t *testing.T) { testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") noNamespaceContext := genericapirequest.NewContext() table := map[string]struct { selectPred storage.SelectionPredicate context genericapirequest.Context }{ "single": { selectPred: matchPodName("foo"), }, "multi": { selectPred: matchPodName("foo", "bar"), }, "singleNoNamespace": { selectPred: matchPodName("foo"), context: noNamespaceContext, }, } for name, m := range table { ctx := testContext if m.context != nil { ctx = m.context } podA := &api.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", Namespace: "test", }, Spec: api.PodSpec{NodeName: "machine"}, } destroyFunc, registry := NewTestGenericStoreRegistry(t) wi, err := registry.WatchPredicate(ctx, m.selectPred, "0") if err != nil { t.Errorf("%v: unexpected error: %v", name, err) } else { obj, err := registry.Create(testContext, podA) if err != nil { got, open := <-wi.ResultChan() if !open { t.Errorf("%v: unexpected channel close", name) } else { if e, a := obj, got.Object; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } } } wi.Stop() } destroyFunc() } }
func (t *Tester) testGetMimatchedNamespace(obj runtime.Object) { ctx1 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar1") ctx2 := genericapirequest.WithNamespace(genericapirequest.NewContext(), "bar2") objMeta := t.getObjectMetaOrFail(obj) objMeta.Name = t.namer(4) objMeta.Namespace = genericapirequest.NamespaceValue(ctx1) _, err := t.storage.(rest.Creater).Create(ctx1, obj) if err != nil { t.Errorf("unexpected error: %v", err) } _, err = t.storage.(rest.Getter).Get(ctx2, t.namer(4), &metav1.GetOptions{}) if t.clusterScope { if err != nil { t.Errorf("unexpected error: %v", err) } } else { if !errors.IsNotFound(err) { t.Errorf("unexpected error returned: %#v", err) } } }
func (a AuthorizerAdapter) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) { list, err := a.Registry.ListRoleBindings(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), &api.ListOptions{}) if err != nil { return nil, err } ret := []*rbac.RoleBinding{} for i := range list.Items { ret = append(ret, &list.Items[i]) } return ret, nil }
func TestEtcdCreateDeploymentRollback(t *testing.T) { ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace) testCases := map[string]struct { rollback extensions.DeploymentRollback errOK func(error) bool }{ "normal": { rollback: extensions.DeploymentRollback{ Name: name, UpdatedAnnotations: map[string]string{}, RollbackTo: extensions.RollbackConfig{Revision: 1}, }, errOK: func(err error) bool { return err == nil }, }, "noAnnotation": { rollback: extensions.DeploymentRollback{ Name: name, RollbackTo: extensions.RollbackConfig{Revision: 1}, }, errOK: func(err error) bool { return err == nil }, }, "noName": { rollback: extensions.DeploymentRollback{ UpdatedAnnotations: map[string]string{}, RollbackTo: extensions.RollbackConfig{Revision: 1}, }, errOK: func(err error) bool { return err != nil }, }, } for k, test := range testCases { storage, server := newStorage(t) rollbackStorage := storage.Rollback if _, err := storage.Deployment.Create(ctx, validNewDeployment()); err != nil { t.Fatalf("%s: unexpected error: %v", k, err) } if _, err := rollbackStorage.Create(ctx, &test.rollback); !test.errOK(err) { t.Errorf("%s: unexpected error: %v", k, err) } else if err == nil { // If rollback succeeded, verify Rollback field of deployment d, err := storage.Deployment.Get(ctx, validNewDeployment().ObjectMeta.Name, &metav1.GetOptions{}) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) } else if !reflect.DeepEqual(*d.(*extensions.Deployment).Spec.RollbackTo, test.rollback.RollbackTo) { t.Errorf("%s: expected: %v, got: %v", k, *d.(*extensions.Deployment).Spec.RollbackTo, test.rollback.RollbackTo) } } storage.Deployment.Store.DestroyFunc() server.Terminate(t) } }
func TestStoreUpdate(t *testing.T) { podA := &api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test"}, Spec: api.PodSpec{NodeName: "machine"}, } podB := &api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test"}, Spec: api.PodSpec{NodeName: "machine2"}, } podAWithResourceVersion := &api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "7"}, Spec: api.PodSpec{NodeName: "machine"}, } testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") destroyFunc, registry := NewTestGenericStoreRegistry(t) defer destroyFunc() // Test1 try to update a non-existing node _, _, err := registry.Update(testContext, podA.Name, rest.DefaultUpdatedObjectInfo(podA, api.Scheme)) if !errors.IsNotFound(err) { t.Errorf("Unexpected error: %v", err) } // Test2 createIfNotFound and verify registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true if !updateAndVerify(t, testContext, registry, podA) { t.Errorf("Unexpected error updating podA") } registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = false // Test3 outofDate _, _, err = registry.Update(testContext, podAWithResourceVersion.Name, rest.DefaultUpdatedObjectInfo(podAWithResourceVersion, api.Scheme)) if !errors.IsConflict(err) { t.Errorf("Unexpected error updating podAWithResourceVersion: %v", err) } // Test4 normal update and verify if !updateAndVerify(t, testContext, registry, podB) { t.Errorf("Unexpected error updating podB") } // Test5 unconditional update // NOTE: The logic for unconditional updates doesn't make sense to me, and imho should be removed. // doUnconditionalUpdate := resourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate() // ^^ That condition can *never be true due to the creation of root objects. // // registry.UpdateStrategy.(*testRESTStrategy).allowUnconditionalUpdate = true // updateAndVerify(t, testContext, registry, podAWithResourceVersion) }
func (t *Tester) testCreateIgnoresContextNamespace(valid runtime.Object) { // Ignore non-empty namespace in context ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "not-default2") // 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, copyOrDie(valid)) if err != nil { t.Fatalf("Unexpected error: %v", err) } defer t.delete(ctx, created) createdObjectMeta := t.getObjectMetaOrFail(created) if createdObjectMeta.Namespace != api.NamespaceNone { t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.Namespace) } }
func TestIgnoreDeleteNotFound(t *testing.T) { pod := validNewPod() testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), api.NamespaceDefault) called := false registry, server := newFailDeleteStorage(t, &called) defer server.Terminate(t) defer registry.Store.DestroyFunc() // should fail if pod A is not created yet. _, err := registry.Delete(testContext, pod.Name, nil) if !errors.IsNotFound(err) { t.Errorf("Unexpected error: %v", err) } // create pod _, err = registry.Create(testContext, pod) if err != nil { t.Errorf("Unexpected error: %v", err) } // delete object with grace period 0, storage will return NotFound, but the // registry shouldn't get any error since we ignore the NotFound error. zero := int64(0) opt := &api.DeleteOptions{GracePeriodSeconds: &zero} obj, err := registry.Delete(testContext, pod.Name, opt) if err != nil { t.Fatalf("Unexpected error: %v", err) } if !called { t.Fatalf("expect the overriding Delete method to be called") } deletedPod, ok := obj.(*api.Pod) if !ok { t.Fatalf("expect a pod is returned") } if deletedPod.DeletionTimestamp == nil { t.Errorf("expect the DeletionTimestamp to be set") } if deletedPod.DeletionGracePeriodSeconds == nil { t.Fatalf("expect the DeletionGracePeriodSeconds to be set") } if *deletedPod.DeletionGracePeriodSeconds != 0 { t.Errorf("expect the DeletionGracePeriodSeconds to be 0, got %d", *deletedPod.DeletionTimestamp) } }
func TestGet(t *testing.T) { storage, _, si, destroyFunc := newStorage(t) defer destroyFunc() ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") key := "/controllers/test/foo" if err := si.Create(ctx, key, &validController, nil, 0); err != nil { t.Fatalf("unexpected error: %v", err) } obj, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } scale := obj.(*extensions.Scale) if scale.Spec.Replicas != validReplicas { t.Errorf("wrong replicas count expected: %d got: %d", validReplicas, scale.Spec.Replicas) } }
func TestScaleUpdate(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) defer storage.ReplicaSet.Store.DestroyFunc() name := "foo" var rs extensions.ReplicaSet ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), api.NamespaceDefault) key := "/replicasets/" + api.NamespaceDefault + "/" + name if err := storage.ReplicaSet.Storage.Create(ctx, key, &validReplicaSet, &rs, 0); err != nil { t.Fatalf("error setting new replica set (key: %s) %v: %v", key, validReplicaSet, err) } replicas := 12 update := extensions.Scale{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: api.NamespaceDefault, }, Spec: extensions.ScaleSpec{ Replicas: int32(replicas), }, } if _, _, err := storage.Scale.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update, api.Scheme)); err != nil { t.Fatalf("error updating scale %v: %v", update, err) } obj, err := storage.Scale.Get(ctx, name, &metav1.GetOptions{}) if err != nil { t.Fatalf("error fetching scale for %s: %v", name, err) } scale := obj.(*extensions.Scale) if scale.Spec.Replicas != int32(replicas) { t.Errorf("wrong replicas count expected: %d got: %d", replicas, scale.Spec.Replicas) } update.ResourceVersion = rs.ResourceVersion update.Spec.Replicas = 15 if _, _, err = storage.Scale.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update, api.Scheme)); err != nil && !errors.IsConflict(err) { t.Fatalf("unexpected error, expecting an update conflict but got %v", err) } }
func TestStatusUpdate(t *testing.T) { storage, statusStorage, server := newStorage(t) defer server.Terminate(t) defer storage.Store.DestroyFunc() ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), api.NamespaceDefault) key := "/poddisruptionbudgets/" + api.NamespaceDefault + "/foo" validPodDisruptionBudget := validNewPodDisruptionBudget() if err := storage.Storage.Create(ctx, key, validPodDisruptionBudget, nil, 0); err != nil { t.Fatalf("unexpected error: %v", err) } obj, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) if err != nil { t.Fatalf("failed to get pdb: %v", err) } obtainedPdb := obj.(*policy.PodDisruptionBudget) update := policy.PodDisruptionBudget{ ObjectMeta: obtainedPdb.ObjectMeta, Spec: policy.PodDisruptionBudgetSpec{ MinAvailable: intstr.FromInt(8), }, Status: policy.PodDisruptionBudgetStatus{ ExpectedPods: 8, }, } if _, _, err := statusStorage.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update, api.Scheme)); err != nil { t.Fatalf("unexpected error: %v", err) } obj, err = storage.Get(ctx, "foo", &metav1.GetOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } pdb := obj.(*policy.PodDisruptionBudget) if pdb.Spec.MinAvailable.IntValue() != 7 { t.Errorf("we expected .spec.replicas to not be updated but it was updated to %v", pdb.Spec.MinAvailable) } if pdb.Status.ExpectedPods != 8 { t.Errorf("we expected .status.replicas to be updated to %d but it was %v", 7, pdb.Status.ExpectedPods) } }
func TestStoreGet(t *testing.T) { podA := &api.Pod{ ObjectMeta: metav1.ObjectMeta{Namespace: "test", Name: "foo"}, Spec: api.PodSpec{NodeName: "machine"}, } testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") destroyFunc, registry := NewTestGenericStoreRegistry(t) defer destroyFunc() _, err := registry.Get(testContext, podA.Name, &metav1.GetOptions{}) if !errors.IsNotFound(err) { t.Errorf("Unexpected error: %v", err) } registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true if !updateAndVerify(t, testContext, registry, podA) { t.Errorf("Unexpected error updating podA") } }
func TestStoreDeleteCollectionNotFound(t *testing.T) { destroyFunc, registry := NewTestGenericStoreRegistry(t) defer destroyFunc() testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") podA := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} podB := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}} for i := 0; i < 10; i++ { // Setup if _, err := registry.Create(testContext, podA); err != nil { t.Errorf("Unexpected error: %v", err) } if _, err := registry.Create(testContext, podB); err != nil { t.Errorf("Unexpected error: %v", err) } // Kick off multiple delete collection calls to test notfound behavior wg := &sync.WaitGroup{} for j := 0; j < 2; j++ { wg.Add(1) go func() { defer wg.Done() _, err := registry.DeleteCollection(testContext, nil, &api.ListOptions{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } }() } wg.Wait() if _, err := registry.Get(testContext, podA.Name, &metav1.GetOptions{}); !errors.IsNotFound(err) { t.Errorf("Unexpected error: %v", err) } if _, err := registry.Get(testContext, podB.Name, &metav1.GetOptions{}); !errors.IsNotFound(err) { t.Errorf("Unexpected error: %v", err) } } }
func TestScaleGet(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) defer storage.ReplicaSet.Store.DestroyFunc() name := "foo" var rs extensions.ReplicaSet ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), api.NamespaceDefault) key := "/replicasets/" + api.NamespaceDefault + "/" + name if err := storage.ReplicaSet.Storage.Create(ctx, key, &validReplicaSet, &rs, 0); err != nil { t.Fatalf("error setting new replica set (key: %s) %v: %v", key, validReplicaSet, err) } want := &extensions.Scale{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: api.NamespaceDefault, UID: rs.UID, ResourceVersion: rs.ResourceVersion, CreationTimestamp: rs.CreationTimestamp, }, Spec: extensions.ScaleSpec{ Replicas: validReplicaSet.Spec.Replicas, }, Status: extensions.ScaleStatus{ Replicas: validReplicaSet.Status.Replicas, Selector: validReplicaSet.Spec.Selector, }, } obj, err := storage.Scale.Get(ctx, name, &metav1.GetOptions{}) got := obj.(*extensions.Scale) if err != nil { t.Fatalf("error fetching scale for %s: %v", name, err) } if !api.Semantic.DeepEqual(got, want) { t.Errorf("unexpected scale: %s", diff.ObjectDiff(got, want)) } }
// getResourceHandler is an HTTP handler function for get requests. It delegates to the // passed-in getterFunc to perform the actual get. func getResourceHandler(scope RequestScope, getter getterFunc) restful.RouteFunction { return func(req *restful.Request, res *restful.Response) { w := res.ResponseWriter namespace, name, err := scope.Namer.Name(req) if err != nil { scope.err(err, res.ResponseWriter, req.Request) return } ctx := scope.ContextFunc(req) ctx = request.WithNamespace(ctx, namespace) result, err := getter(ctx, name, req) if err != nil { scope.err(err, res.ResponseWriter, req.Request) return } if err := setSelfLink(result, req, scope.Namer); err != nil { scope.err(err, res.ResponseWriter, req.Request) return } responsewriters.WriteObject(http.StatusOK, scope.Kind.GroupVersion(), scope.Serializer, result, w, req.Request) } }