func TestUpdate(t *testing.T) { fakeEtcdClient, etcdStorage := newEtcdStorage(t) storage := NewStorage(etcdStorage) test := resttest.New(t, storage, fakeEtcdClient.SetError) key, err := storage.KeyFunc(test.TestContext(), "foo") if err != nil { t.Fatal(err) } key = etcdtest.AddPrefix(key) fakeEtcdClient.ExpectNotFoundGet(key) fakeEtcdClient.ChangeIndex = 2 serviceAccount := validNewServiceAccount("foo") existing := validNewServiceAccount("exists") existing.Namespace = test.TestNamespace() obj, err := storage.Create(test.TestContext(), existing) if err != nil { t.Fatalf("unable to create object: %v", err) } older := obj.(*api.ServiceAccount) older.ResourceVersion = "1" test.TestUpdate( serviceAccount, existing, older, ) }
func TestDelete(t *testing.T) { ctx := api.NewContext() storage, fakeEtcdClient := newStorage(t) test := resttest.New(t, storage, fakeEtcdClient.SetError).ClusterScope() node := validChangedNode() key, _ := storage.KeyFunc(ctx, node.Name) key = etcdtest.AddPrefix(key) createFn := func() runtime.Object { fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(latest.Codec, node), ModifiedIndex: 1, }, }, } return node } gracefulSetFn := func() bool { if fakeEtcdClient.Data[key].R.Node == nil { return false } return fakeEtcdClient.Data[key].R.Node.TTL == 30 } test.TestDeleteNoGraceful(createFn, gracefulSetFn) }
func TestEtcdGetEndpoints(t *testing.T) { ctx := api.NewDefaultContext() storage, fakeClient := newStorage(t) endpoints := validNewEndpoints() name := endpoints.Name key, _ := storage.KeyFunc(ctx, name) key = etcdtest.AddPrefix(key) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, endpoints), 0) response, err := fakeClient.Get(key, false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var endpointsOut api.Endpoints err = latest.Codec.DecodeInto([]byte(response.Node.Value), &endpointsOut) if err != nil { t.Errorf("unexpected error: %v", err) } obj, err := storage.Get(ctx, name) if err != nil { t.Errorf("unexpected error: %v", err) } got := obj.(*api.Endpoints) endpoints.ObjectMeta.ResourceVersion = got.ObjectMeta.ResourceVersion if e, a := endpoints, got; !api.Semantic.DeepEqual(*e, *a) { t.Errorf("Unexpected endpoints: %#v, expected %#v", e, a) } }
func TestDelete(t *testing.T) { ctx := api.NewDefaultContext() storage, _, fakeEtcdClient, _ := newStorage(t) test := resttest.New(t, storage, fakeEtcdClient.SetError) pv := validChangedPersistentVolumeClaim() key, _ := storage.KeyFunc(ctx, pv.Name) key = etcdtest.AddPrefix(key) createFn := func() runtime.Object { fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(latest.Codec, pv), ModifiedIndex: 1, }, }, } return pv } gracefulSetFn := func() bool { if fakeEtcdClient.Data[key].R.Node == nil { return false } return fakeEtcdClient.Data[key].R.Node.TTL == 30 } test.TestDelete(createFn, gracefulSetFn) }
// Ensure that when scheduler creates a binding for a pod that has already been deleted // by the API server, API server returns not-found error. func TestEtcdCreateBindingNoPod(t *testing.T) { storage, bindingStorage, _, server := newStorage(t) defer server.Terminate(t) defer storage.Store.DestroyFunc() ctx := api.NewDefaultContext() key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) // Assume that a pod has undergone the following: // - Create (apiserver) // - Schedule (scheduler) // - Delete (apiserver) _, err := bindingStorage.Create(ctx, &api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "foo"}, Target: api.ObjectReference{Name: "machine"}, }) if err == nil { t.Fatalf("Expected not-found-error but got nothing") } if !errors.IsNotFound(storeerr.InterpretGetError(err, api.Resource("pods"), "foo")) { t.Fatalf("Unexpected error returned: %#v", err) } _, err = storage.Get(ctx, "foo") if err == nil { t.Fatalf("Expected not-found-error but got nothing") } if !errors.IsNotFound(storeerr.InterpretGetError(err, api.Resource("pods"), "foo")) { t.Fatalf("Unexpected error: %v", err) } }
func TestUpdate(t *testing.T) { storage, fakeEtcdClient, _ := newStorage(t) test := resttest.New(t, storage, fakeEtcdClient.SetError) key, err := storage.KeyFunc(test.TestContext(), "foo") if err != nil { t.Fatal(err) } key = etcdtest.AddPrefix(key) fakeEtcdClient.ExpectNotFoundGet(key) fakeEtcdClient.ChangeIndex = 2 rsrc := validNewThirdPartyResource("foo") existing := validNewThirdPartyResource("exists") existing.Namespace = test.TestNamespace() obj, err := storage.Create(test.TestContext(), existing) if err != nil { t.Fatalf("unable to create object: %v", err) } older := obj.(*expapi.ThirdPartyResource) older.ResourceVersion = "1" test.TestUpdate( rsrc, existing, older, ) }
func TestEtcdCreateWithExistingContainers(t *testing.T) { storage, bindingStorage, _, server := newStorage(t) defer server.Terminate(t) defer storage.Store.DestroyFunc() ctx := api.NewDefaultContext() key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) _, err := storage.Create(ctx, validNewPod()) if err != nil { t.Fatalf("unexpected error: %v", err) } // Suddenly, a wild scheduler appears: _, err = bindingStorage.Create(ctx, &api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "foo"}, Target: api.ObjectReference{Name: "machine"}, }) if err != nil { t.Fatalf("unexpected error: %v", err) } _, err = storage.Get(ctx, "foo") if err != nil { t.Fatalf("Unexpected error %v", err) } }
func TestEtcdCreateWithContainersNotFound(t *testing.T) { storage, bindingStorage, _, server := newStorage(t) defer server.Terminate(t) defer storage.Store.DestroyFunc() ctx := api.NewDefaultContext() key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) _, err := storage.Create(ctx, validNewPod()) if err != nil { t.Fatalf("unexpected error: %v", err) } // Suddenly, a wild scheduler appears: _, err = bindingStorage.Create(ctx, &api.Binding{ ObjectMeta: api.ObjectMeta{ Namespace: api.NamespaceDefault, Name: "foo", Annotations: map[string]string{"label1": "value1"}, }, Target: api.ObjectReference{Name: "machine"}, }) if err != nil { t.Fatalf("unexpected error: %v", err) } obj, err := storage.Get(ctx, "foo") if err != nil { t.Fatalf("Unexpected error %v", err) } pod := obj.(*api.Pod) if !(pod.Annotations != nil && pod.Annotations["label1"] == "value1") { t.Fatalf("Pod annotations don't match the expected: %v", pod.Annotations) } }
func TestEtcdGetPersistentVolumes(t *testing.T) { ctx := api.NewContext() storage, _, fakeClient, _ := newStorage(t) persistentVolume := validNewPersistentVolume("foo") name := persistentVolume.Name key, _ := storage.KeyFunc(ctx, name) key = etcdtest.AddPrefix(key) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, persistentVolume), 0) response, err := fakeClient.Get(key, false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var persistentVolumeOut api.PersistentVolume err = latest.Codec.DecodeInto([]byte(response.Node.Value), &persistentVolumeOut) if err != nil { t.Errorf("unexpected error: %v", err) } obj, err := storage.Get(ctx, name) if err != nil { t.Errorf("unexpected error: %v", err) } got := obj.(*api.PersistentVolume) persistentVolume.ObjectMeta.ResourceVersion = got.ObjectMeta.ResourceVersion if e, a := persistentVolume, got; !api.Semantic.DeepEqual(*e, *a) { t.Errorf("Unexpected persistentVolume: %#v, expected %#v", e, a) } }
func TestEtcdUpdatePersistentVolumes(t *testing.T) { ctx := api.NewContext() storage, _, fakeClient, _ := newStorage(t) persistentVolume := validChangedPersistentVolume() key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPersistentVolume("foo")), 0) _, _, err := storage.Update(ctx, persistentVolume) if err != nil { t.Errorf("unexpected error: %v", err) } response, err := fakeClient.Get(key, false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var persistentVolumeOut api.PersistentVolume err = latest.Codec.DecodeInto([]byte(response.Node.Value), &persistentVolumeOut) if err != nil { t.Errorf("unexpected error: %v", err) } persistentVolume.ObjectMeta.ResourceVersion = persistentVolumeOut.ObjectMeta.ResourceVersion if !api.Semantic.DeepEqual(persistentVolume, &persistentVolumeOut) { t.Errorf("Unexpected persistentVolume: %#v, expected %#v", &persistentVolumeOut, persistentVolume) } }
func TestEtcdCreateWithExistingContainers(t *testing.T) { storage, bindingStorage, _, fakeClient := newStorage(t) ctx := api.NewDefaultContext() fakeClient.TestIndex = true key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) fakeClient.ExpectNotFoundGet(key) _, err := storage.Create(ctx, validNewPod()) if err != nil { t.Fatalf("unexpected error: %v", err) } // Suddenly, a wild scheduler appears: _, err = bindingStorage.Create(ctx, &api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "foo"}, Target: api.ObjectReference{Name: "machine"}, }) if err != nil { t.Fatalf("unexpected error: %v", err) } resp, err := fakeClient.Get(key, false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var pod api.Pod err = testapi.Default.Codec().DecodeInto([]byte(resp.Node.Value), &pod) if err != nil { t.Errorf("unexpected error: %v", err) } if pod.Name != "foo" { t.Errorf("Unexpected pod: %#v %s", pod, resp.Node.Value) } }
func TestEtcdUpdateNotScheduled(t *testing.T) { storage, _, _, server := newStorage(t) defer server.Terminate(t) defer storage.Store.DestroyFunc() ctx := api.NewDefaultContext() key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) if _, err := storage.Create(ctx, validNewPod()); err != nil { t.Fatalf("unexpected error: %v", err) } podIn := validChangedPod() _, _, err := storage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(podIn, api.Scheme)) if err != nil { t.Errorf("Unexpected error: %v", err) } obj, err := storage.Get(ctx, validNewPod().ObjectMeta.Name) if err != nil { t.Errorf("unexpected error: %v", err) } podOut := obj.(*api.Pod) // validChangedPod only changes the Labels, so were checking the update was valid if !api.Semantic.DeepEqual(podIn.Labels, podOut.Labels) { t.Errorf("objects differ: %v", diff.ObjectDiff(podOut, podIn)) } }
func TestEtcdCreateWithConflict(t *testing.T) { storage, bindingStorage, _, fakeClient := newStorage(t) ctx := api.NewDefaultContext() fakeClient.TestIndex = true key, _ := storage.KeyFunc(ctx, "foo") fakeClient.ExpectNotFoundGet(key) _, err := storage.Create(ctx, validNewPod()) if err != nil { t.Fatalf("unexpected error: %v", err) } // Suddenly, a wild scheduler appears: binding := api.Binding{ ObjectMeta: api.ObjectMeta{ Namespace: api.NamespaceDefault, Name: "foo", Annotations: map[string]string{"label1": "value1"}, }, Target: api.ObjectReference{Name: "machine"}, } _, err = bindingStorage.Create(ctx, &binding) if err != nil { t.Fatalf("unexpected error: %v", err) } _, err = bindingStorage.Create(ctx, &binding) if err == nil || !errors.IsConflict(err) { t.Fatalf("expected resource conflict error, not: %v", err) } }
func TestUpdate(t *testing.T) { fakeClient, helper := newHelper(t) storage := NewREST(helper, nil).Route test := resttest.New(t, storage, fakeClient.SetError) key, err := storage.KeyFunc(test.TestContext(), "foo") if err != nil { t.Fatal(err) } key = etcdtest.AddPrefix(key) fakeClient.ExpectNotFoundGet(key) fakeClient.ChangeIndex = 2 route := validNewRoute("foo") route.Namespace = test.TestNamespace() existing := validNewRoute("exists") existing.Namespace = test.TestNamespace() obj, err := storage.Create(test.TestContext(), existing) if err != nil { t.Fatalf("unable to create object: %v", err) } older := obj.(*api.Route) older.ResourceVersion = "1" test.TestUpdate( route, existing, older, ) }
func TestEtcdUpdateEndpoints(t *testing.T) { ctx := api.NewDefaultContext() storage, fakeClient := newStorage(t) endpoints := validChangedEndpoints() key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewEndpoints()), 0) _, _, err := storage.Update(ctx, endpoints) if err != nil { t.Errorf("unexpected error: %v", err) } response, err := fakeClient.Get(key, false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var endpointsOut api.Endpoints err = latest.Codec.DecodeInto([]byte(response.Node.Value), &endpointsOut) if err != nil { t.Errorf("unexpected error: %v", err) } endpoints.ObjectMeta.ResourceVersion = endpointsOut.ObjectMeta.ResourceVersion if !api.Semantic.DeepEqual(endpoints, &endpointsOut) { t.Errorf("Unexpected endpoints: %#v, expected %#v", &endpointsOut, endpoints) } }
func TestDelete(t *testing.T) { ctx := api.NewDefaultContext() storage, fakeEtcdClient, _ := newStorage(t) test := resttest.New(t, storage, fakeEtcdClient.SetError) rsrc := validNewThirdPartyResource("foo2") key, _ := storage.KeyFunc(ctx, "foo2") key = etcdtest.AddPrefix(key) createFn := func() runtime.Object { fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(testapi.Codec(), rsrc), ModifiedIndex: 1, }, }, } return rsrc } gracefulSetFn := func() bool { if fakeEtcdClient.Data[key].R.Node == nil { return false } return fakeEtcdClient.Data[key].R.Node.TTL == 30 } test.TestDeleteNoGraceful(createFn, gracefulSetFn) }
func TestEtcdUpdateEndpoints(t *testing.T) { ctx := api.NewContext() storage, fakeClient := newStorage(t) node := validChangedNode() key, _ := storage.KeyFunc(ctx, node.Name) key = etcdtest.AddPrefix(key) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewNode()), 0) _, _, err := storage.Update(ctx, node) if err != nil { t.Errorf("unexpected error: %v", err) } response, err := fakeClient.Get(key, false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var nodeOut api.Node err = latest.Codec.DecodeInto([]byte(response.Node.Value), &nodeOut) if err != nil { t.Errorf("unexpected error: %v", err) } node.ObjectMeta.ResourceVersion = nodeOut.ObjectMeta.ResourceVersion if !api.Semantic.DeepEqual(node, &nodeOut) { t.Errorf("Unexpected node: %#v, expected %#v", &nodeOut, node) } }
func TestEtcdUpdateStatus(t *testing.T) { storage, statusStorage, fakeClient, etcdStorage := newStorage(t) ctx := api.NewDefaultContext() fakeClient.TestIndex = true key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) pvcStart := validNewPersistentVolumeClaim("foo", api.NamespaceDefault) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, pvcStart), 1) pvc := &api.PersistentVolumeClaim{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: api.NamespaceDefault, ResourceVersion: "1", }, Spec: api.PersistentVolumeClaimSpec{ AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, Resources: api.ResourceRequirements{ Requests: api.ResourceList{ api.ResourceName(api.ResourceStorage): resource.MustParse("3Gi"), }, }, }, Status: api.PersistentVolumeClaimStatus{ Phase: api.ClaimBound, }, } expected := *pvcStart expected.ResourceVersion = "2" expected.Labels = pvc.Labels expected.Status = pvc.Status _, _, err := statusStorage.Update(ctx, pvc) if err != nil { t.Fatalf("Unexpected error: %v", err) } var pvcOut api.PersistentVolumeClaim key, _ = storage.KeyFunc(ctx, "foo") if err := etcdStorage.Get(key, &pvcOut, false); err != nil { t.Fatalf("Unexpected error: %v", err) } if !api.Semantic.DeepEqual(expected, pvcOut) { t.Errorf("unexpected object: %s", util.ObjectDiff(expected, pvcOut)) } }
func TestEtcdCreateBinding(t *testing.T) { ctx := api.NewDefaultContext() testCases := map[string]struct { binding api.Binding errOK func(error) bool }{ "noName": { binding: api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "foo"}, Target: api.ObjectReference{}, }, errOK: func(err error) bool { return err != nil }, }, "badKind": { binding: api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "foo"}, Target: api.ObjectReference{Name: "machine1", Kind: "unknown"}, }, errOK: func(err error) bool { return err != nil }, }, "emptyKind": { binding: api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "foo"}, Target: api.ObjectReference{Name: "machine2"}, }, errOK: func(err error) bool { return err == nil }, }, "kindNode": { binding: api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "foo"}, Target: api.ObjectReference{Name: "machine3", Kind: "Node"}, }, errOK: func(err error) bool { return err == nil }, }, } for k, test := range testCases { storage, bindingStorage, _, server := newStorage(t) key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) if _, err := storage.Create(ctx, validNewPod()); err != nil { t.Fatalf("%s: unexpected error: %v", k, err) } if _, err := bindingStorage.Create(ctx, &test.binding); !test.errOK(err) { t.Errorf("%s: unexpected error: %v", k, err) } else if err == nil { // If bind succeeded, verify Host field in pod's Spec. pod, err := storage.Get(ctx, validNewPod().ObjectMeta.Name) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) } else if pod.(*api.Pod).Spec.NodeName != test.binding.Target.Name { t.Errorf("%s: expected: %v, got: %v", k, pod.(*api.Pod).Spec.NodeName, test.binding.Target.Name) } } storage.Store.DestroyFunc() server.Terminate(t) } }
func TestEtcdUpdateStatus(t *testing.T) { storage, statusStorage, fakeClient, etcdStorage := newStorage(t) ctx := api.NewContext() fakeClient.TestIndex = true key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) pvStart := validNewPersistentVolume("foo") fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, pvStart), 1) pvIn := &api.PersistentVolume{ ObjectMeta: api.ObjectMeta{ Name: "foo", ResourceVersion: "1", }, Status: api.PersistentVolumeStatus{ Phase: api.VolumeBound, }, } expected := *pvStart expected.ResourceVersion = "2" expected.Labels = pvIn.Labels expected.Status = pvIn.Status _, _, err := statusStorage.Update(ctx, pvIn) if err != nil { t.Fatalf("Unexpected error: %v", err) } var pvOut api.PersistentVolume key, _ = storage.KeyFunc(ctx, "foo") if err := etcdStorage.Get(key, &pvOut, false); err != nil { t.Fatalf("Unexpected error: %v", err) } if !api.Semantic.DeepEqual(expected, pvOut) { t.Errorf("unexpected object: %s", util.ObjectDiff(expected, pvOut)) } }
func TestUpdateStatus(t *testing.T) { storage, status, fakeClient := newStorage(t) ctx := api.NewDefaultContext() key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) resourcequotaStart := validNewResourceQuota() fakeClient.Set(key, runtime.EncodeOrDie(testapi.Default.Codec(), resourcequotaStart), 0) resourcequotaIn := &api.ResourceQuota{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: api.NamespaceDefault, ResourceVersion: "1", }, Status: api.ResourceQuotaStatus{ Used: api.ResourceList{ api.ResourceCPU: resource.MustParse("1"), api.ResourceMemory: resource.MustParse("1Gi"), api.ResourcePods: resource.MustParse("1"), api.ResourceServices: resource.MustParse("1"), api.ResourceReplicationControllers: resource.MustParse("1"), api.ResourceQuotas: resource.MustParse("1"), }, Hard: api.ResourceList{ api.ResourceCPU: resource.MustParse("100"), api.ResourceMemory: resource.MustParse("4Gi"), api.ResourcePods: resource.MustParse("10"), api.ResourceServices: resource.MustParse("10"), api.ResourceReplicationControllers: resource.MustParse("10"), api.ResourceQuotas: resource.MustParse("1"), }, }, } expected := *resourcequotaStart expected.ResourceVersion = "2" expected.Labels = resourcequotaIn.Labels expected.Status = resourcequotaIn.Status _, _, err := status.Update(ctx, resourcequotaIn) if err != nil { t.Fatalf("Unexpected error: %v", err) } rqOut, err := storage.Get(ctx, "foo") if !api.Semantic.DeepEqual(&expected, rqOut) { t.Errorf("unexpected object: %s", util.ObjectDiff(&expected, rqOut)) } }
func TestEtcdGetNode(t *testing.T) { ctx := api.NewContext() storage, fakeClient := newStorage(t) node := validNewNode() key, _ := storage.KeyFunc(ctx, node.Name) key = etcdtest.AddPrefix(key) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, node), 0) nodeObj, err := storage.Get(ctx, node.Name) if err != nil { t.Errorf("unexpected error: %v", err) } got := nodeObj.(*api.Node) node.ObjectMeta.ResourceVersion = got.ObjectMeta.ResourceVersion if e, a := node, got; !api.Semantic.DeepEqual(*e, *a) { t.Errorf("Unexpected node: %#v, expected %#v", e, a) } }
func TestEtcdDeleteNode(t *testing.T) { ctx := api.NewContext() storage, fakeClient := newStorage(t) node := validNewNode() key, _ := storage.KeyFunc(ctx, node.Name) key = etcdtest.AddPrefix(key) fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, node), 0) _, err := storage.Delete(ctx, node.Name, nil) if err != nil { t.Errorf("unexpected error: %v", err) } if len(fakeClient.DeletedKeys) != 1 { t.Errorf("Expected 1 delete, found %#v", fakeClient.DeletedKeys) } if fakeClient.DeletedKeys[0] != key { t.Errorf("Unexpected key: %s, expected %s", fakeClient.DeletedKeys[0], key) } }
func TestDeleteEndpoints(t *testing.T) { ctx := api.NewDefaultContext() storage, fakeClient := newStorage(t) endpoints := validNewEndpoints() name := endpoints.Name key, _ := storage.KeyFunc(ctx, name) key = etcdtest.AddPrefix(key) fakeClient.ChangeIndex = 1 fakeClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(latest.Codec, endpoints), ModifiedIndex: 1, CreatedIndex: 1, }, }, } _, err := storage.Delete(ctx, name, nil) if err != nil { t.Fatalf("unexpected error: %v", err) } }
func TestDeletePersistentVolumes(t *testing.T) { ctx := api.NewContext() storage, _, fakeClient, _ := newStorage(t) persistentVolume := validNewPersistentVolume("foo") name := persistentVolume.Name key, _ := storage.KeyFunc(ctx, name) key = etcdtest.AddPrefix(key) fakeClient.ChangeIndex = 1 fakeClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(latest.Codec, persistentVolume), ModifiedIndex: 1, CreatedIndex: 1, }, }, } _, err := storage.Delete(ctx, name, nil) if err != nil { t.Fatalf("unexpected error: %v", err) } }
func TestDelete(t *testing.T) { fakeClient, helper := newHelper(t) storage := NewREST(helper, nil).Route test := resttest.New(t, storage, fakeClient.SetError) ctx := kapi.NewDefaultContext() validRoute := validNewRoute("test") validRoute.Namespace = kapi.NamespaceDefault key, _ := storage.KeyFunc(ctx, validRoute.Name) key = etcdtest.AddPrefix(key) createFn := func() runtime.Object { obj := validRoute obj.ResourceVersion = "1" fakeClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(testapi.Codec(), obj), ModifiedIndex: 1, }, }, } return obj } gracefulSetFn := func() bool { // If the controller is still around after trying to delete either the delete // failed, or we're deleting it gracefully. if fakeClient.Data[key].R.Node != nil { return true } return false } test.TestDelete(createFn, gracefulSetFn) }
func TestEtcdUpdateNotScheduled(t *testing.T) { storage, _, _, fakeClient := newStorage(t) ctx := api.NewDefaultContext() fakeClient.TestIndex = true key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) fakeClient.Set(key, runtime.EncodeOrDie(testapi.Default.Codec(), validNewPod()), 1) podIn := validChangedPod() _, _, err := storage.Update(ctx, podIn) if err != nil { t.Errorf("Unexpected error: %v", err) } response, err := fakeClient.Get(key, false, false) if err != nil { t.Fatalf("Unexpected error: %v", err) } podOut := &api.Pod{} testapi.Default.Codec().DecodeInto([]byte(response.Node.Value), podOut) if !api.Semantic.DeepEqual(podOut, podIn) { t.Errorf("objects differ: %v", util.ObjectDiff(podOut, podIn)) } }
func TestEtcdUpdateStatus(t *testing.T) { storage, _, statusStorage, server := newStorage(t) defer server.Terminate(t) defer storage.Store.DestroyFunc() ctx := api.NewDefaultContext() key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) podStart := api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: api.NamespaceDefault, }, Spec: api.PodSpec{ NodeName: "machine", Containers: []api.Container{ { Image: "foo:v1", SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), }, }, SecurityContext: &api.PodSecurityContext{}, }, } err := storage.Storage.Create(ctx, key, &podStart, nil, 0) if err != nil { t.Errorf("unexpected error: %v", err) } podIn := api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Labels: map[string]string{ "foo": "bar", }, }, Spec: api.PodSpec{ NodeName: "machine", Containers: []api.Container{ { Image: "foo:v2", ImagePullPolicy: api.PullIfNotPresent, TerminationMessagePath: api.TerminationMessagePathDefault, }, }, SecurityContext: &api.PodSecurityContext{}, }, Status: api.PodStatus{ Phase: api.PodRunning, PodIP: "127.0.0.1", Message: "is now scheduled", }, } expected := podStart expected.ResourceVersion = "2" grace := int64(30) expected.Spec.TerminationGracePeriodSeconds = &grace expected.Spec.RestartPolicy = api.RestartPolicyAlways expected.Spec.DNSPolicy = api.DNSClusterFirst expected.Spec.Containers[0].ImagePullPolicy = api.PullIfNotPresent expected.Spec.Containers[0].TerminationMessagePath = api.TerminationMessagePathDefault expected.Labels = podIn.Labels expected.Status = podIn.Status _, _, err = statusStorage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(&podIn, api.Scheme)) if err != nil { t.Fatalf("Unexpected error: %v", err) } obj, err := storage.Get(ctx, "foo") if err != nil { t.Errorf("unexpected error: %v", err) } podOut := obj.(*api.Pod) // Check to verify the Label, and Status updates match from change above. Those are the fields changed. if !api.Semantic.DeepEqual(podOut.Spec, expected.Spec) || !api.Semantic.DeepEqual(podOut.Labels, expected.Labels) || !api.Semantic.DeepEqual(podOut.Status, expected.Status) { t.Errorf("objects differ: %v", diff.ObjectDiff(podOut, expected)) } }
func TestEtcdUpdateScheduled(t *testing.T) { storage, _, _, server := newStorage(t) defer server.Terminate(t) defer storage.Store.DestroyFunc() ctx := api.NewDefaultContext() key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) err := storage.Storage.Create(ctx, key, &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: api.NamespaceDefault, }, Spec: api.PodSpec{ NodeName: "machine", Containers: []api.Container{ { Name: "foobar", Image: "foo:v1", SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), }, }, SecurityContext: &api.PodSecurityContext{}, }, }, nil, 1) if err != nil { t.Errorf("Unexpected error: %v", err) } grace := int64(30) podIn := api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Labels: map[string]string{ "foo": "bar", }, }, Spec: api.PodSpec{ NodeName: "machine", Containers: []api.Container{{ Name: "foobar", Image: "foo:v2", ImagePullPolicy: api.PullIfNotPresent, TerminationMessagePath: api.TerminationMessagePathDefault, SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), }}, RestartPolicy: api.RestartPolicyAlways, DNSPolicy: api.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, SecurityContext: &api.PodSecurityContext{}, }, } _, _, err = storage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(&podIn, api.Scheme)) if err != nil { t.Errorf("Unexpected error: %v", err) } obj, err := storage.Get(ctx, "foo") if err != nil { t.Errorf("Unexpected error: %v", err) } podOut := obj.(*api.Pod) // Check to verify the Spec and Label updates match from change above. Those are the fields changed. if !api.Semantic.DeepEqual(podOut.Spec, podIn.Spec) || !api.Semantic.DeepEqual(podOut.Labels, podIn.Labels) { t.Errorf("objects differ: %v", diff.ObjectDiff(podOut, podIn)) } }
func TestResourceLocation(t *testing.T) { expectedIP := "1.2.3.4" testCases := []struct { pod api.Pod query string location string }{ { pod: api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Status: api.PodStatus{PodIP: expectedIP}, }, query: "foo", location: expectedIP, }, { pod: api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Status: api.PodStatus{PodIP: expectedIP}, }, query: "foo:12345", location: expectedIP + ":12345", }, { pod: api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.PodSpec{ Containers: []api.Container{ {Name: "ctr"}, }, }, Status: api.PodStatus{PodIP: expectedIP}, }, query: "foo", location: expectedIP, }, { pod: api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.PodSpec{ Containers: []api.Container{ {Name: "ctr", Ports: []api.ContainerPort{{ContainerPort: 9376}}}, }, }, Status: api.PodStatus{PodIP: expectedIP}, }, query: "foo", location: expectedIP + ":9376", }, { pod: api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.PodSpec{ Containers: []api.Container{ {Name: "ctr", Ports: []api.ContainerPort{{ContainerPort: 9376}}}, }, }, Status: api.PodStatus{PodIP: expectedIP}, }, query: "foo:12345", location: expectedIP + ":12345", }, { pod: api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.PodSpec{ Containers: []api.Container{ {Name: "ctr1"}, {Name: "ctr2", Ports: []api.ContainerPort{{ContainerPort: 9376}}}, }, }, Status: api.PodStatus{PodIP: expectedIP}, }, query: "foo", location: expectedIP + ":9376", }, { pod: api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.PodSpec{ Containers: []api.Container{ {Name: "ctr1", Ports: []api.ContainerPort{{ContainerPort: 9376}}}, {Name: "ctr2", Ports: []api.ContainerPort{{ContainerPort: 1234}}}, }, }, Status: api.PodStatus{PodIP: expectedIP}, }, query: "foo", location: expectedIP + ":9376", }, } ctx := api.NewDefaultContext() for _, tc := range testCases { storage, _, _, server := newStorage(t) key, _ := storage.KeyFunc(ctx, tc.pod.Name) key = etcdtest.AddPrefix(key) if err := storage.Storage.Create(ctx, key, &tc.pod, nil, 0); err != nil { t.Fatalf("unexpected error: %v", err) } redirector := rest.Redirector(storage) location, _, err := redirector.ResourceLocation(api.NewDefaultContext(), tc.query) if err != nil { t.Errorf("Unexpected error: %v", err) } if location == nil { t.Errorf("Unexpected nil: %v", location) } if location.Scheme != "" { t.Errorf("Expected '%v', but got '%v'", "", location.Scheme) } if location.Host != tc.location { t.Errorf("Expected %v, but got %v", tc.location, location.Host) } server.Terminate(t) } }