func testData() (*api.PodList, *api.ServiceList) { pods := &api.PodList{ ListMeta: unversioned.ListMeta{ ResourceVersion: "15", }, Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"}, Spec: apitesting.DeepEqualSafePodSpec(), }, }, } svc := &api.ServiceList{ ListMeta: unversioned.ListMeta{ ResourceVersion: "16", }, Items: []api.Service{ { ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, Spec: api.ServiceSpec{ Type: "ClusterIP", SessionAffinity: "None", }, }, }, } return pods, svc }
func TestList(t *testing.T) { server := etcdtesting.NewEtcdTestClientServer(t) defer server.Terminate(t) key := etcdtest.AddPrefix("/some/key") helper := newEtcdHelper(server.Client, testapi.Default.Codec(), key) list := api.PodList{ Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "bar"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "baz"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: apitesting.DeepEqualSafePodSpec(), }, }, } createPodList(t, helper, &list) var got api.PodList // TODO: a sorted filter function could be applied such implied // ordering on the returned list doesn't matter. err := helper.List(context.TODO(), key, 0, storage.Everything, &got) if err != nil { t.Errorf("Unexpected error %v", err) } if e, a := list.Items, got.Items; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } }
func TestList(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) helper := newEtcdHelper(fakeClient, testapi.Default.Codec(), etcdtest.PathPrefix()) key := etcdtest.AddPrefix("/some/key") fakeClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ EtcdIndex: 10, Node: &etcd.Node{ Dir: true, Nodes: []*etcd.Node{ { Key: "/foo", Value: getEncodedPod("foo"), Dir: false, ModifiedIndex: 1, }, { Key: "/bar", Value: getEncodedPod("bar"), Dir: false, ModifiedIndex: 2, }, { Key: "/baz", Value: getEncodedPod("baz"), Dir: false, ModifiedIndex: 3, }, }, }, }, } expect := api.PodList{ ListMeta: unversioned.ListMeta{ResourceVersion: "10"}, Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "2"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "baz", ResourceVersion: "3"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, Spec: apitesting.DeepEqualSafePodSpec(), }, }, } var got api.PodList err := helper.List(context.TODO(), "/some/key", storage.Everything, &got) if err != nil { t.Errorf("Unexpected error %v", err) } if e, a := expect, got; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } }
func TestGetSortedObjects(t *testing.T) { pods := &api.PodList{ ListMeta: unversioned.ListMeta{ ResourceVersion: "15", }, Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "c", Namespace: "test", ResourceVersion: "10"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "11"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "9"}, Spec: apitesting.DeepEqualSafePodSpec(), }, }, } f, tf, codec, ns := NewAPIFactory() tf.Printer = &testPrinter{} tf.Client = &fake.RESTClient{ NegotiatedSerializer: ns, Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, } tf.Namespace = "test" tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}}} buf := bytes.NewBuffer([]byte{}) errBuf := bytes.NewBuffer([]byte{}) cmd := NewCmdGet(f, buf, errBuf) cmd.SetOutput(buf) // sorting with metedata.name cmd.Flags().Set("sort-by", ".metadata.name") cmd.Run(cmd, []string{"pods"}) // expect sorted: a,b,c expected := []runtime.Object{&pods.Items[2], &pods.Items[1], &pods.Items[0]} actual := tf.Printer.(*testPrinter).Objects if !reflect.DeepEqual(expected, actual) { t.Errorf("unexpected object: %#v", actual) } if len(buf.String()) == 0 { t.Errorf("unexpected empty output") } }
func TestModifyHostConfig(t *testing.T) { nilPrivSC := fullValidSecurityContext() nilPrivSC.Privileged = nil nilPrivHC := fullValidHostConfig() nilPrivHC.Privileged = false nilCapsSC := fullValidSecurityContext() nilCapsSC.Capabilities = nil nilCapsHC := fullValidHostConfig() nilCapsHC.CapAdd = *new([]string) nilCapsHC.CapDrop = *new([]string) nilSELinuxSC := fullValidSecurityContext() nilSELinuxSC.SELinuxOptions = nil nilSELinuxHC := fullValidHostConfig() nilSELinuxHC.SecurityOpt = *new([]string) seLinuxLabelsSC := fullValidSecurityContext() seLinuxLabelsHC := fullValidHostConfig() testCases := map[string]struct { securityContext *api.SecurityContext expected *docker.HostConfig }{ "full settings": { securityContext: fullValidSecurityContext(), expected: fullValidHostConfig(), }, "nil privileged": { securityContext: nilPrivSC, expected: nilPrivHC, }, "nil capabilities": { securityContext: nilCapsSC, expected: nilCapsHC, }, "nil selinux options": { securityContext: nilSELinuxSC, expected: nilSELinuxHC, }, "selinux labels": { securityContext: seLinuxLabelsSC, expected: seLinuxLabelsHC, }, } provider := NewSimpleSecurityContextProvider() dummyContainer := &api.Container{} dummyPod := &api.Pod{ Spec: apitesting.DeepEqualSafePodSpec(), } for k, v := range testCases { dummyContainer.SecurityContext = v.securityContext dockerCfg := &docker.HostConfig{} provider.ModifyHostConfig(dummyPod, dummyContainer, dockerCfg) if !reflect.DeepEqual(v.expected, dockerCfg) { t.Errorf("unexpected modification of host config for %s. Expected: %#v Got: %#v", k, v.expected, dockerCfg) } } }
// TestListAcrossDirectories ensures that the client excludes directories and flattens tree-response - simulates cross-namespace query func TestListAcrossDirectories(t *testing.T) { server := etcdtesting.NewEtcdTestClientServer(t) defer server.Terminate(t) rootkey := etcdtest.AddPrefix("/some/key") key1 := etcdtest.AddPrefix("/some/key/directory1") key2 := etcdtest.AddPrefix("/some/key/directory2") roothelper := newEtcdHelper(server.Client, testapi.Default.Codec(), rootkey) helper1 := newEtcdHelper(server.Client, testapi.Default.Codec(), key1) helper2 := newEtcdHelper(server.Client, testapi.Default.Codec(), key2) list := api.PodList{ Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "baz"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "bar"}, Spec: apitesting.DeepEqualSafePodSpec(), }, }, } returnedObj := &api.Pod{} // create the 1st 2 elements in one directory createObj(t, helper1, list.Items[0].Name, &list.Items[0], returnedObj, 0) list.Items[0] = *returnedObj createObj(t, helper1, list.Items[1].Name, &list.Items[1], returnedObj, 0) list.Items[1] = *returnedObj // create the last element in the other directory createObj(t, helper2, list.Items[2].Name, &list.Items[2], returnedObj, 0) list.Items[2] = *returnedObj var got api.PodList err := roothelper.List(context.TODO(), rootkey, "", storage.Everything, &got) if err != nil { t.Errorf("Unexpected error %v", err) } if e, a := list.Items, got.Items; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } }
func testData() (*api.PodList, *api.ServiceList, *api.ReplicationControllerList) { pods := &api.PodList{ ListMeta: unversioned.ListMeta{ ResourceVersion: "15", }, Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"}, Spec: apitesting.DeepEqualSafePodSpec(), }, }, } svc := &api.ServiceList{ ListMeta: unversioned.ListMeta{ ResourceVersion: "16", }, Items: []api.Service{ { ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, Spec: api.ServiceSpec{ SessionAffinity: "None", Type: api.ServiceTypeClusterIP, }, }, }, } rc := &api.ReplicationControllerList{ ListMeta: unversioned.ListMeta{ ResourceVersion: "17", }, Items: []api.ReplicationController{ { ObjectMeta: api.ObjectMeta{Name: "rc1", Namespace: "test", ResourceVersion: "18"}, Spec: api.ReplicationControllerSpec{ Replicas: 1, }, }, }, } return pods, svc, rc }
func TestListFiltered(t *testing.T) { server := etcdtesting.NewEtcdTestClientServer(t) defer server.Terminate(t) key := etcdtest.AddPrefix("/some/key") helper := newEtcdHelper(server.Client, testapi.Default.Codec(), key) list := api.PodList{ Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "bar"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "baz"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: apitesting.DeepEqualSafePodSpec(), }, }, } createPodList(t, helper, &list) // List only "bar" pod p := storage.SelectionPredicate{ Label: labels.Everything(), Field: fields.SelectorFromSet(fields.Set{"metadata.name": "bar"}), GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) { pod := obj.(*api.Pod) return labels.Set(pod.Labels), fields.Set{"metadata.name": pod.Name}, nil }, } var got api.PodList err := helper.List(context.TODO(), key, "", p, &got) if err != nil { t.Errorf("Unexpected error %v", err) } // Check to make certain that the filter function only returns "bar" if e, a := list.Items[0], got.Items[0]; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } }
func TestListFiltered(t *testing.T) { server := etcdtesting.NewEtcdTestClientServer(t) defer server.Terminate(t) key := etcdtest.AddPrefix("/some/key") helper := newEtcdHelper(server.Client, testapi.Default.Codec(), key) list := api.PodList{ Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "bar"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "baz"}, Spec: apitesting.DeepEqualSafePodSpec(), }, { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: apitesting.DeepEqualSafePodSpec(), }, }, } createPodList(t, helper, &list) filterFunc := func(obj runtime.Object) bool { pod := obj.(*api.Pod) return pod.Name == "bar" } filter := storage.NewSimpleFilter(filterFunc, storage.NoTriggerFunc) var got api.PodList err := helper.List(context.TODO(), key, "", filter, &got) if err != nil { t.Errorf("Unexpected error %v", err) } // Check to make certain that the filter function only returns "bar" if e, a := list.Items[0], got.Items[0]; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } }
func TestModifyHostConfigPodSecurityContext(t *testing.T) { supplementalGroupsSC := &api.PodSecurityContext{} supplementalGroupsSC.SupplementalGroups = []int64{2222} supplementalGroupHC := fullValidHostConfig() supplementalGroupHC.GroupAdd = []string{"2222"} fsGroupHC := fullValidHostConfig() fsGroupHC.GroupAdd = []string{"1234"} bothHC := fullValidHostConfig() bothHC.GroupAdd = []string{"2222", "1234"} fsGroup := int64(1234) testCases := map[string]struct { securityContext *api.PodSecurityContext expected *docker.HostConfig }{ "nil": { securityContext: nil, expected: fullValidHostConfig(), }, "SupplementalGroup": { securityContext: supplementalGroupsSC, expected: supplementalGroupHC, }, "FSGroup": { securityContext: &api.PodSecurityContext{FSGroup: &fsGroup}, expected: fsGroupHC, }, "FSGroup + SupplementalGroups": { securityContext: &api.PodSecurityContext{ SupplementalGroups: []int64{2222}, FSGroup: &fsGroup, }, expected: bothHC, }, } provider := NewSimpleSecurityContextProvider() dummyContainer := &api.Container{} dummyContainer.SecurityContext = fullValidSecurityContext() dummyPod := &api.Pod{ Spec: apitesting.DeepEqualSafePodSpec(), } for k, v := range testCases { dummyPod.Spec.SecurityContext = v.securityContext dockerCfg := &docker.HostConfig{} provider.ModifyHostConfig(dummyPod, dummyContainer, dockerCfg) if !reflect.DeepEqual(v.expected, dockerCfg) { t.Errorf("unexpected modification of host config for %s. Expected: %#v Got: %#v", k, v.expected, dockerCfg) } } }
func watchTestData() ([]api.Pod, []watch.Event) { pods := []api.Pod{ { ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: "test", ResourceVersion: "10", }, Spec: apitesting.DeepEqualSafePodSpec(), }, } events := []watch.Event{ { Type: watch.Modified, Object: &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: "test", ResourceVersion: "11", }, Spec: apitesting.DeepEqualSafePodSpec(), }, }, { Type: watch.Deleted, Object: &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: "test", ResourceVersion: "12", }, Spec: apitesting.DeepEqualSafePodSpec(), }, }, } return pods, events }
func TestGet(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) helper := newEtcdHelper(fakeClient, testapi.Default.Codec(), etcdtest.PathPrefix()) key := etcdtest.AddPrefix("/some/key") expect := api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: apitesting.DeepEqualSafePodSpec(), } fakeClient.Set(key, runtime.EncodeOrDie(testapi.Default.Codec(), &expect), 0) var got api.Pod err := helper.Get(context.TODO(), "/some/key", &got, false) if err != nil { t.Errorf("Unexpected error %#v", err) } if !reflect.DeepEqual(got, expect) { t.Errorf("Wanted %#v, got %#v", expect, got) } }
func TestDefaultErrorFunc(t *testing.T) { testPod := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: apitesting.DeepEqualSafePodSpec(), } handler := util.FakeHandler{ StatusCode: 200, ResponseBody: runtime.EncodeOrDie(testapi.Default.Codec(), testPod), T: t, } mux := http.NewServeMux() // FakeHandler musn't be sent requests other than the one you want to test. mux.Handle(testapi.Default.ResourcePath("pods", "bar", "foo"), &handler) server := httptest.NewServer(mux) // TODO: Uncomment when fix #19254 // defer server.Close() factory := NewConfigFactory(client.NewOrDie(&client.Config{Host: server.URL, GroupVersion: testapi.Default.GroupVersion()}), nil, api.DefaultSchedulerName) queue := cache.NewFIFO(cache.MetaNamespaceKeyFunc) podBackoff := podBackoff{ perPodBackoff: map[types.NamespacedName]*backoffEntry{}, clock: &fakeClock{}, defaultDuration: 1 * time.Millisecond, maxDuration: 1 * time.Second, } errFunc := factory.makeDefaultErrorFunc(&podBackoff, queue) errFunc(testPod, nil) for { // This is a terrible way to do this but I plan on replacing this // whole error handling system in the future. The test will time // out if something doesn't work. time.Sleep(10 * time.Millisecond) got, exists, _ := queue.Get(testPod) if !exists { continue } handler.ValidateRequest(t, testapi.Default.ResourcePath("pods", "bar", "foo"), "GET", nil) if e, a := testPod, got; !reflect.DeepEqual(e, a) { t.Errorf("Expected %v, got %v", e, a) } break } }
func TestGet(t *testing.T) { server := etcdtesting.NewEtcdTestClientServer(t) defer server.Terminate(t) key := etcdtest.AddPrefix("/some/key") helper := newEtcdHelper(server.Client, testapi.Default.Codec(), key) expect := api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: apitesting.DeepEqualSafePodSpec(), } var got api.Pod if err := helper.Create(context.TODO(), key, &expect, &got, 0); err != nil { t.Errorf("Unexpected error %#v", err) } expect = got if err := helper.Get(context.TODO(), key, &got, false); err != nil { t.Errorf("Unexpected error %#v", err) } if !reflect.DeepEqual(got, expect) { t.Errorf("Wanted %#v, got %#v", expect, got) } }
func makeTestPod(name string) *api.Pod { return &api.Pod{ ObjectMeta: api.ObjectMeta{Namespace: "ns", Name: name}, Spec: apitesting.DeepEqualSafePodSpec(), } }
func TestUpdateWithRetries(t *testing.T) { codec := testapi.Default.Codec() rc := &api.ReplicationController{ ObjectMeta: api.ObjectMeta{Name: "rc", Labels: map[string]string{ "foo": "bar", }, }, Spec: api.ReplicationControllerSpec{ Selector: map[string]string{ "foo": "bar", }, Template: &api.PodTemplateSpec{ ObjectMeta: api.ObjectMeta{ Labels: map[string]string{ "foo": "bar", }, }, Spec: apitesting.DeepEqualSafePodSpec(), }, }, } // Test end to end updating of the rc with retries. Essentially make sure the update handler // sees the right updates, failures in update/get are handled properly, and that the updated // rc with new resource version is returned to the caller. Without any of these rollingupdate // will fail cryptically. newRc := *rc newRc.ResourceVersion = "2" newRc.Spec.Selector["baz"] = "foobar" header := http.Header{} header.Set("Content-Type", runtime.ContentTypeJSON) updates := []*http.Response{ {StatusCode: 500, Header: header, Body: objBody(codec, &api.ReplicationController{})}, {StatusCode: 500, Header: header, Body: objBody(codec, &api.ReplicationController{})}, {StatusCode: 200, Header: header, Body: objBody(codec, &newRc)}, } gets := []*http.Response{ {StatusCode: 500, Header: header, Body: objBody(codec, &api.ReplicationController{})}, {StatusCode: 200, Header: header, Body: objBody(codec, rc)}, } fakeClient := &fake.RESTClient{ Codec: codec, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == testapi.Default.ResourcePath("replicationcontrollers", "default", "rc") && m == "PUT": update := updates[0] updates = updates[1:] // We should always get an update with a valid rc even when the get fails. The rc should always // contain the update. if c, ok := readOrDie(t, req, codec).(*api.ReplicationController); !ok || !reflect.DeepEqual(rc, c) { t.Errorf("Unexpected update body, got %+v expected %+v", c, rc) } else if sel, ok := c.Spec.Selector["baz"]; !ok || sel != "foobar" { t.Errorf("Expected selector label update, got %+v", c.Spec.Selector) } else { delete(c.Spec.Selector, "baz") } return update, nil case p == testapi.Default.ResourcePath("replicationcontrollers", "default", "rc") && m == "GET": get := gets[0] gets = gets[1:] return get, nil default: t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } }), } clientConfig := &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} client := client.NewOrDie(clientConfig) client.Client = fakeClient.Client if rc, err := updateWithRetries( client.ReplicationControllers("default"), rc, func(c *api.ReplicationController) { c.Spec.Selector["baz"] = "foobar" }); err != nil { t.Errorf("unexpected error: %v", err) } else if sel, ok := rc.Spec.Selector["baz"]; !ok || sel != "foobar" || rc.ResourceVersion != "2" { t.Errorf("Expected updated rc, got %+v", rc) } if len(updates) != 0 || len(gets) != 0 { t.Errorf("Remaining updates %+v gets %+v", updates, gets) } }
func TestMerge(t *testing.T) { grace := int64(30) tests := []struct { obj runtime.Object fragment string expected runtime.Object expectErr bool kind string }{ { kind: "Pod", obj: &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", }, }, fragment: fmt.Sprintf(`{ "apiVersion": "%s" }`, testapi.Default.GroupVersion().String()), expected: &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", }, Spec: apitesting.DeepEqualSafePodSpec(), }, }, /* TODO: uncomment this test once Merge is updated to use strategic-merge-patch. See #8449. { kind: "Pod", obj: &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", }, Spec: api.PodSpec{ Containers: []api.Container{ api.Container{ Name: "c1", Image: "red-image", }, api.Container{ Name: "c2", Image: "blue-image", }, }, }, }, fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "containers": [ { "name": "c1", "image": "green-image" } ] } }`, testapi.Default.GroupVersion().String()), expected: &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", }, Spec: api.PodSpec{ Containers: []api.Container{ api.Container{ Name: "c1", Image: "green-image", }, api.Container{ Name: "c2", Image: "blue-image", }, }, }, }, }, */ { kind: "Pod", obj: &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", }, }, fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "volumes": [ {"name": "v1"}, {"name": "v2"} ] } }`, testapi.Default.GroupVersion().String()), expected: &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", }, Spec: api.PodSpec{ Volumes: []api.Volume{ { Name: "v1", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}, }, { Name: "v2", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}, }, }, RestartPolicy: api.RestartPolicyAlways, DNSPolicy: api.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, SecurityContext: &api.PodSecurityContext{}, }, }, }, { kind: "Pod", obj: &api.Pod{}, fragment: "invalid json", expected: &api.Pod{}, expectErr: true, }, { kind: "Service", obj: &api.Service{}, fragment: `{ "apiVersion": "badVersion" }`, expectErr: true, }, { kind: "Service", obj: &api.Service{ Spec: api.ServiceSpec{}, }, fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "ports": [ { "port": 0 } ] } }`, testapi.Default.GroupVersion().String()), expected: &api.Service{ Spec: api.ServiceSpec{ SessionAffinity: "None", Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{ { Protocol: api.ProtocolTCP, Port: 0, }, }, }, }, }, { kind: "Service", obj: &api.Service{ Spec: api.ServiceSpec{ Selector: map[string]string{ "version": "v1", }, }, }, fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "selector": { "version": "v2" } } }`, testapi.Default.GroupVersion().String()), expected: &api.Service{ Spec: api.ServiceSpec{ SessionAffinity: "None", Type: api.ServiceTypeClusterIP, Selector: map[string]string{ "version": "v2", }, }, }, }, } for i, test := range tests { out, err := Merge(test.obj, test.fragment, test.kind) if !test.expectErr { if err != nil { t.Errorf("testcase[%d], unexpected error: %v", i, err) } else if !reflect.DeepEqual(out, test.expected) { t.Errorf("\n\ntestcase[%d]\nexpected:\n%+v\nsaw:\n%+v", i, test.expected, out) } } if test.expectErr && err == nil { t.Errorf("testcase[%d], unexpected non-error", i) } } }
func TestHelperCreate(t *testing.T) { expectPost := func(req *http.Request) bool { if req.Method != "POST" { t.Errorf("unexpected method: %#v", req) return false } parts := splitPath(req.URL.Path) if parts[1] != "bar" { t.Errorf("url doesn't contain namespace: %#v", req) return false } return true } tests := []struct { Resp *http.Response HttpErr error Modify bool Object runtime.Object ExpectObject runtime.Object Err bool Req func(*http.Request) bool }{ { HttpErr: errors.New("failure"), Err: true, }, { Resp: &http.Response{ StatusCode: http.StatusNotFound, Header: header(), Body: objBody(&unversioned.Status{Status: unversioned.StatusFailure}), }, Err: true, }, { Resp: &http.Response{ StatusCode: http.StatusOK, Header: header(), Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess}), }, Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, ExpectObject: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, Req: expectPost, }, { Modify: false, Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}}, ExpectObject: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}}, Resp: &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, Req: expectPost, }, { Modify: true, Object: &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}, Spec: apitesting.DeepEqualSafePodSpec(), }, ExpectObject: &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: apitesting.DeepEqualSafePodSpec(), }, Resp: &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, Req: expectPost, }, } for i, test := range tests { client := &fake.RESTClient{ NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), Resp: test.Resp, Err: test.HttpErr, } modifier := &Helper{ RESTClient: client, Versioner: testapi.Default.MetadataAccessor(), NamespaceScoped: true, } _, err := modifier.Create("bar", test.Modify, test.Object) if (err != nil) != test.Err { t.Errorf("%d: unexpected error: %t %v", i, test.Err, err) } if err != nil { continue } if test.Req != nil && !test.Req(client.Req) { t.Errorf("%d: unexpected request: %#v", i, client.Req) } body, err := ioutil.ReadAll(client.Req.Body) if err != nil { t.Fatalf("%d: unexpected error: %#v", i, err) } t.Logf("got body: %s", string(body)) expect := []byte{} if test.ExpectObject != nil { expect = []byte(runtime.EncodeOrDie(testapi.Default.Codec(), test.ExpectObject)) } if !reflect.DeepEqual(expect, body) { t.Errorf("%d: unexpected body: %s (expected %s)", i, string(body), string(expect)) } } }
func TestHelperReplace(t *testing.T) { expectPut := func(path string, req *http.Request) bool { if req.Method != "PUT" { t.Errorf("unexpected method: %#v", req) return false } if req.URL.Path != path { t.Errorf("unexpected url: %v", req.URL) return false } return true } tests := []struct { Resp *http.Response HTTPClient *http.Client HttpErr error Overwrite bool Object runtime.Object Namespace string NamespaceScoped bool ExpectPath string ExpectObject runtime.Object Err bool Req func(string, *http.Request) bool }{ { Namespace: "bar", NamespaceScoped: true, HttpErr: errors.New("failure"), Err: true, }, { Namespace: "bar", NamespaceScoped: true, Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, Resp: &http.Response{ StatusCode: http.StatusNotFound, Header: header(), Body: objBody(&unversioned.Status{Status: unversioned.StatusFailure}), }, Err: true, }, { Namespace: "bar", NamespaceScoped: true, Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, ExpectPath: "/namespaces/bar/foo", ExpectObject: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, Resp: &http.Response{ StatusCode: http.StatusOK, Header: header(), Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess}), }, Req: expectPut, }, // namespace scoped resource { Namespace: "bar", NamespaceScoped: true, Object: &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: apitesting.DeepEqualSafePodSpec(), }, ExpectPath: "/namespaces/bar/foo", ExpectObject: &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}, Spec: apitesting.DeepEqualSafePodSpec(), }, Overwrite: true, HTTPClient: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { if req.Method == "PUT" { return &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, nil } return &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}})}, nil }), Req: expectPut, }, // cluster scoped resource { Object: &api.Node{ ObjectMeta: api.ObjectMeta{Name: "foo"}, }, ExpectObject: &api.Node{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}, }, Overwrite: true, ExpectPath: "/foo", HTTPClient: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { if req.Method == "PUT" { return &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, nil } return &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&api.Node{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}})}, nil }), Req: expectPut, }, { Namespace: "bar", NamespaceScoped: true, Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}}, ExpectPath: "/namespaces/bar/foo", ExpectObject: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}}, Resp: &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, Req: expectPut, }, } for i, test := range tests { client := &fake.RESTClient{ Client: test.HTTPClient, NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), Resp: test.Resp, Err: test.HttpErr, } modifier := &Helper{ RESTClient: client, Versioner: testapi.Default.MetadataAccessor(), NamespaceScoped: test.NamespaceScoped, } _, err := modifier.Replace(test.Namespace, "foo", test.Overwrite, test.Object) if (err != nil) != test.Err { t.Errorf("%d: unexpected error: %t %v", i, test.Err, err) } if err != nil { continue } if test.Req != nil && !test.Req(test.ExpectPath, client.Req) { t.Errorf("%d: unexpected request: %#v", i, client.Req) } body, err := ioutil.ReadAll(client.Req.Body) if err != nil { t.Fatalf("%d: unexpected error: %#v", i, err) } expect := []byte{} if test.ExpectObject != nil { expect = []byte(runtime.EncodeOrDie(testapi.Default.Codec(), test.ExpectObject)) } if !reflect.DeepEqual(expect, body) { t.Errorf("%d: unexpected body: %s", i, string(body)) } } }
func TestHelperReplace(t *testing.T) { expectPut := func(req *http.Request) bool { if req.Method != "PUT" { t.Errorf("unexpected method: %#v", req) return false } parts := splitPath(req.URL.Path) if parts[1] != "bar" { t.Errorf("url doesn't contain namespace: %#v", req.URL) return false } if parts[2] != "foo" { t.Errorf("url doesn't contain name: %#v", req) return false } return true } tests := []struct { Resp *http.Response RespFunc fake.HTTPClientFunc HttpErr error Overwrite bool Object runtime.Object ExpectObject runtime.Object Err bool Req func(*http.Request) bool }{ { HttpErr: errors.New("failure"), Err: true, }, { Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, Resp: &http.Response{ StatusCode: http.StatusNotFound, Body: objBody(&unversioned.Status{Status: unversioned.StatusFailure}), }, Err: true, }, { Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, ExpectObject: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, Resp: &http.Response{ StatusCode: http.StatusOK, Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess}), }, Req: expectPut, }, { Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, ExpectObject: &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}, Spec: apitesting.DeepEqualSafePodSpec(), }, Overwrite: true, RespFunc: func(req *http.Request) (*http.Response, error) { if req.Method == "PUT" { return &http.Response{StatusCode: http.StatusOK, Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, nil } return &http.Response{StatusCode: http.StatusOK, Body: objBody(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}})}, nil }, Req: expectPut, }, { Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}}, ExpectObject: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}}, Resp: &http.Response{StatusCode: http.StatusOK, Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, Req: expectPut, }, } for i, test := range tests { client := &fake.RESTClient{ Codec: testapi.Default.Codec(), Resp: test.Resp, Err: test.HttpErr, } if test.RespFunc != nil { client.Client = test.RespFunc } modifier := &Helper{ RESTClient: client, Codec: testapi.Default.Codec(), Versioner: testapi.Default.MetadataAccessor(), NamespaceScoped: true, } data := []byte{} if test.Object != nil { data = []byte(runtime.EncodeOrDie(testapi.Default.Codec(), test.Object)) } _, err := modifier.Replace("bar", "foo", test.Overwrite, data) if (err != nil) != test.Err { t.Errorf("%d: unexpected error: %t %v", i, test.Err, err) } if err != nil { continue } if test.Req != nil && !test.Req(client.Req) { t.Errorf("%d: unexpected request: %#v", i, client.Req) } body, err := ioutil.ReadAll(client.Req.Body) if err != nil { t.Fatalf("%d: unexpected error: %#v", i, err) } t.Logf("got body: %s", string(body)) expect := []byte{} if test.ExpectObject != nil { expect = []byte(runtime.EncodeOrDie(testapi.Default.Codec(), test.ExpectObject)) } if !reflect.DeepEqual(expect, body) { t.Errorf("%d: unexpected body: %s", i, string(body)) } } }