func makeTestServer(t *testing.T, namespace, name string, podResponse, controllerResponse, updateResponse serverResponse) (*httptest.Server, *util.FakeHandler) { fakePodHandler := util.FakeHandler{ StatusCode: podResponse.statusCode, ResponseBody: runtime.EncodeOrDie(testapi.Codec(), podResponse.obj.(runtime.Object)), } fakeControllerHandler := util.FakeHandler{ StatusCode: controllerResponse.statusCode, ResponseBody: runtime.EncodeOrDie(testapi.Codec(), controllerResponse.obj.(runtime.Object)), } fakeUpdateHandler := util.FakeHandler{ StatusCode: updateResponse.statusCode, ResponseBody: runtime.EncodeOrDie(testapi.Codec(), updateResponse.obj.(runtime.Object)), } mux := http.NewServeMux() mux.Handle(testapi.ResourcePath("pods", namespace, ""), &fakePodHandler) mux.Handle(testapi.ResourcePath(replicationControllerResourceName(), "", ""), &fakeControllerHandler) if namespace != "" { mux.Handle(testapi.ResourcePath(replicationControllerResourceName(), namespace, ""), &fakeControllerHandler) } if name != "" { mux.Handle(testapi.ResourcePath(replicationControllerResourceName(), namespace, name), &fakeUpdateHandler) } mux.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) { t.Errorf("unexpected request: %v", req.RequestURI) res.WriteHeader(http.StatusNotFound) }) return httptest.NewServer(mux), &fakeUpdateHandler }
func TestSetObjWithoutResourceVersioner(t *testing.T) { obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} fakeClient := NewFakeEtcdClient(t) helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix()) helper.Versioner = nil returnedObj := &api.Pod{} err := helper.SetObj("/some/key", obj, returnedObj, 3) key := etcdtest.AddPrefix("/some/key") if err != nil { t.Errorf("Unexpected error %#v", err) } data, err := testapi.Codec().Encode(obj) if err != nil { t.Errorf("Unexpected error %#v", err) } expect := string(data) got := fakeClient.Data[key].R.Node.Value if expect != got { t.Errorf("Wanted %v, got %v", expect, got) } if e, a := uint64(3), fakeClient.LastSetTTL; e != a { t.Errorf("Wanted %v, got %v", e, a) } if obj.ResourceVersion != returnedObj.ResourceVersion || obj.Name != returnedObj.Name { t.Errorf("If set was successful but returned object did not have correct resource version") } }
func TestDoRequestNewWayFile(t *testing.T) { reqObj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} reqBodyExpected, err := testapi.Codec().Encode(reqObj) if err != nil { t.Errorf("unexpected error: %v", err) } file, err := ioutil.TempFile("", "foo") if err != nil { t.Errorf("unexpected error: %v", err) } _, err = file.Write(reqBodyExpected) if err != nil { t.Errorf("unexpected error: %v", err) } expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: util.NewIntOrStringFromInt(12345), }}}} expectedBody, _ := testapi.Codec().Encode(expectedObj) fakeHandler := util.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) c := NewOrDie(&Config{Host: testServer.URL, Version: testapi.Version(), Username: "******", Password: "******"}) wasCreated := true obj, err := c.Verb("POST"). Prefix("foo/bar", "baz"). Timeout(time.Second). Body(file.Name()). Do().WasCreated(&wasCreated).Get() if err != nil { t.Errorf("Unexpected error: %v %#v", err, err) return } if obj == nil { t.Error("nil obj") } else if !api.Semantic.DeepDerivative(expectedObj, obj) { t.Errorf("Expected: %#v, got %#v", expectedObj, obj) } if wasCreated { t.Errorf("expected object was not created") } tmpStr := string(reqBodyExpected) requestURL := testapi.ResourcePathWithPrefix("foo/bar/baz", "", "", "") requestURL += "?timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) if fakeHandler.RequestReceived.Header["Authorization"] == nil { t.Errorf("Request is missing authorization header: %#v", *fakeHandler.RequestReceived) } }
func TestWatch(t *testing.T) { client := framework.NewEtcdClient() helper := tools.NewEtcdHelper(client, testapi.Codec(), etcdtest.PathPrefix()) framework.WithEtcdKey(func(key string) { key = etcdtest.AddPrefix(key) resp, err := client.Set(key, runtime.EncodeOrDie(testapi.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0) if err != nil { t.Fatalf("unexpected error: %v", err) } expectedVersion := resp.Node.ModifiedIndex // watch should load the object at the current index w, err := helper.Watch(key, 0, tools.Everything) if err != nil { t.Fatalf("Unexpected error: %v", err) } event := <-w.ResultChan() if event.Type != watch.Added || event.Object == nil { t.Fatalf("expected first value to be set to ADDED, got %#v", event) } // version should match what we set pod := event.Object.(*api.Pod) if pod.ResourceVersion != strconv.FormatUint(expectedVersion, 10) { t.Errorf("expected version %d, got %#v", expectedVersion, pod) } // should be no events in the stream select { case event, ok := <-w.ResultChan(): if !ok { t.Fatalf("channel closed unexpectedly") } t.Fatalf("unexpected object in channel: %#v", event) default: } // should return the previously deleted item in the watch, but with the latest index resp, err = client.Delete(key, false) if err != nil { t.Fatalf("unexpected error: %v", err) } expectedVersion = resp.Node.ModifiedIndex event = <-w.ResultChan() if event.Type != watch.Deleted { t.Errorf("expected deleted event %#v", event) } pod = event.Object.(*api.Pod) if pod.ResourceVersion != strconv.FormatUint(expectedVersion, 10) { t.Errorf("expected version %d, got %#v", expectedVersion, pod) } }) }
func TestDecoder(t *testing.T) { table := []watch.EventType{watch.Added, watch.Deleted, watch.Modified, watch.Error} for _, eventType := range table { out, in := io.Pipe() decoder := NewDecoder(out, testapi.Codec()) expect := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} encoder := json.NewEncoder(in) go func() { data, err := testapi.Codec().Encode(expect) if err != nil { t.Fatalf("Unexpected error %v", err) } if err := encoder.Encode(&WatchEvent{eventType, runtime.RawExtension{json.RawMessage(data)}}); err != nil { t.Errorf("Unexpected error %v", err) } in.Close() }() done := make(chan struct{}) go func() { action, got, err := decoder.Decode() if err != nil { t.Fatalf("Unexpected error %v", err) } if e, a := eventType, action; e != a { t.Errorf("Expected %v, got %v", e, a) } if e, a := expect, got; !api.Semantic.DeepDerivative(e, a) { t.Errorf("Expected %v, got %v", e, a) } t.Logf("Exited read") close(done) }() <-done done = make(chan struct{}) go func() { _, _, err := decoder.Decode() if err == nil { t.Errorf("Unexpected nil error") } close(done) }() <-done decoder.Close() } }
func NewTestEventEtcdRegistry(t *testing.T) (*tools.FakeEtcdClient, generic.Registry) { f := tools.NewFakeEtcdClient(t) f.TestIndex = true h := tools.NewEtcdHelper(f, testapi.Codec(), etcdtest.PathPrefix()) return f, NewEtcdRegistry(h, testTTL) }
func TestDoRequestBearer(t *testing.T) { status := &api.Status{Status: api.StatusFailure} expectedBody, _ := latest.Codec.Encode(status) fakeHandler := util.FakeHandler{ StatusCode: 400, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() request, _ := http.NewRequest("GET", testServer.URL, nil) c, err := RESTClientFor(&Config{ Host: testServer.URL, Version: testapi.Version(), Codec: testapi.Codec(), BearerToken: "test", }) if err != nil { t.Fatalf("unexpected error: %v", err) } err = c.Get().Do().Error() if err == nil { t.Fatalf("unexpected non-error: %v", err) } if fakeHandler.RequestReceived.Header.Get("Authorization") != "Bearer test" { t.Errorf("Request is missing authorization header: %#v", *request) } }
func TestValidateOk(t *testing.T) { schema, err := loadSchemaForTest() if err != nil { t.Errorf("Failed to load: %v", err) } tests := []struct { obj runtime.Object typeName string }{ {obj: &api.Pod{}}, {obj: &api.Service{}}, {obj: &api.ReplicationController{}}, } seed := rand.Int63() apiObjectFuzzer := apitesting.FuzzerFor(nil, "", rand.NewSource(seed)) for i := 0; i < 5; i++ { for _, test := range tests { testObj := test.obj apiObjectFuzzer.Fuzz(testObj) data, err := testapi.Codec().Encode(testObj) if err != nil { t.Errorf("unexpected error: %v", err) } err = schema.ValidateBytes(data) if err != nil { t.Errorf("unexpected error: %v", err) } } } }
func TestSetsCodec(t *testing.T) { testCases := map[string]struct { Err bool Prefix string Codec runtime.Codec }{ testapi.Version(): {false, "/api/" + testapi.Version() + "/", testapi.Codec()}, "invalidVersion": {true, "", nil}, } for version, expected := range testCases { client, err := New(&Config{Host: "127.0.0.1", Version: version}) switch { case err == nil && expected.Err: t.Errorf("expected error but was nil") continue case err != nil && !expected.Err: t.Errorf("unexpected error %v", err) continue case err != nil: continue } if e, a := expected.Prefix, client.RESTClient.baseURL.Path; e != a { t.Errorf("expected %#v, got %#v", e, a) } if e, a := expected.Codec, client.RESTClient.Codec; e != a { t.Errorf("expected %#v, got %#v", e, a) } } }
func body(obj runtime.Object, raw *string) *string { if obj != nil { bs, _ := testapi.Codec().Encode(obj) body := string(bs) return &body } return raw }
func TestEtcdDelete(t *testing.T) { podA := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, Spec: api.PodSpec{NodeName: "machine"}, } nodeWithPodA := tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(testapi.Codec(), podA), ModifiedIndex: 1, CreatedIndex: 1, }, }, E: nil, } emptyNode := tools.EtcdResponseWithError{ R: &etcd.Response{}, E: tools.EtcdErrorNotFound, } key := "foo" table := map[string]struct { existing tools.EtcdResponseWithError expect tools.EtcdResponseWithError errOK func(error) bool }{ "normal": { existing: nodeWithPodA, expect: emptyNode, errOK: func(err error) bool { return err == nil }, }, "notExisting": { existing: emptyNode, expect: emptyNode, errOK: func(err error) bool { return errors.IsNotFound(err) }, }, } for name, item := range table { fakeClient, registry := NewTestGenericEtcdRegistry(t) path := etcdtest.AddPrefix("pods/foo") fakeClient.Data[path] = item.existing obj, err := registry.Delete(api.NewContext(), key, nil) if !item.errOK(err) { t.Errorf("%v: unexpected error: %v (%#v)", name, err, obj) } if item.expect.E != nil { item.expect.E.(*etcd.EtcdError).Index = fakeClient.ChangeIndex } if e, a := item.expect, fakeClient.Data[path]; !api.Semantic.DeepDerivative(e, a) { t.Errorf("%v:\n%s", name, util.ObjectDiff(e, a)) } } }
func TestEncodeDecodeRoundTrip(t *testing.T) { testCases := []struct { Type watch.EventType Object runtime.Object Codec runtime.Codec }{ { watch.Added, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, testapi.Codec(), }, { watch.Modified, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, testapi.Codec(), }, { watch.Deleted, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, testapi.Codec(), }, } for i, testCase := range testCases { buf := &bytes.Buffer{} encoder := NewEncoder(buf, testCase.Codec) if err := encoder.Encode(&watch.Event{Type: testCase.Type, Object: testCase.Object}); err != nil { t.Errorf("%d: unexpected error: %v", i, err) continue } decoder := NewDecoder(ioutil.NopCloser(buf), testCase.Codec) event, obj, err := decoder.Decode() if err != nil { t.Errorf("%d: unexpected error: %v", i, err) continue } if !api.Semantic.DeepDerivative(testCase.Object, obj) { t.Errorf("%d: expected %#v, got %#v", i, testCase.Object, obj) } if event != testCase.Type { t.Errorf("%d: unexpected type: %#v", i, event) } } }
func TestCreateObjNilOutParam(t *testing.T) { obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} fakeClient := NewFakeEtcdClient(t) helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix()) err := helper.CreateObj("/some/key", obj, nil, 5) if err != nil { t.Errorf("Unexpected error %#v", err) } }
func testPrinter(t *testing.T, printer ResourcePrinter, unmarshalFunc func(data []byte, v interface{}) error) { buf := bytes.NewBuffer([]byte{}) err := printer.PrintObj(&testData, buf) if err != nil { t.Fatal(err) } var poutput testStruct // Verify that given function runs without error. err = unmarshalFunc(buf.Bytes(), &poutput) if err != nil { t.Fatal(err) } // Use real decode function to undo the versioning process. poutput = testStruct{} err = runtime.YAMLDecoder(testapi.Codec()).DecodeInto(buf.Bytes(), &poutput) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(testData, poutput) { t.Errorf("Test data and unmarshaled data are not equal: %v", util.ObjectDiff(poutput, testData)) } obj := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, } buf.Reset() printer.PrintObj(obj, buf) var objOut api.Pod // Verify that given function runs without error. err = unmarshalFunc(buf.Bytes(), &objOut) if err != nil { t.Fatalf("unexpected error: %#v", err) } // Use real decode function to undo the versioning process. objOut = api.Pod{} err = runtime.YAMLDecoder(testapi.Codec()).DecodeInto(buf.Bytes(), &objOut) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(obj, &objOut) { t.Errorf("Unexpected inequality:\n%v", util.ObjectDiff(obj, &objOut)) } }
func TestMigrateKeys(t *testing.T) { withEtcdKey(func(oldPrefix string) { client := newEtcdClient() helper := tools.NewEtcdHelper(client, testapi.Codec(), oldPrefix) key1 := oldPrefix + "/obj1" key2 := oldPrefix + "/foo/obj2" key3 := oldPrefix + "/foo/bar/obj3" // Create a new entres - these are the 'existing' entries with old prefix _, _ = helper.Client.Create(key1, "foo", 0) _, _ = helper.Client.Create(key2, "foo", 0) _, _ = helper.Client.Create(key3, "foo", 0) // Change the helper to a new prefix newPrefix := "/qingyuan" helper = tools.NewEtcdHelper(client, testapi.Codec(), newPrefix) // Migrate the keys err := helper.MigrateKeys(oldPrefix) if err != nil { t.Fatalf("Unexpected error: %v", err) } // Check the resources are at the correct new location newNames := []string{ newPrefix + "/obj1", newPrefix + "/foo/obj2", newPrefix + "/foo/bar/obj3", } for _, name := range newNames { _, err := helper.Client.Get(name, false, false) if err != nil { t.Fatalf("Unexpected error: %v", err) } } // Check the old locations are removed if _, err := helper.Client.Get(oldPrefix, false, false); err == nil { t.Fatalf("Old directory still exists.") } }) }
func TestSetObjFailCAS(t *testing.T) { obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}} fakeClient := NewFakeEtcdClient(t) fakeClient.CasErr = fakeClient.NewError(123) helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix()) err := helper.SetObj("/some/key", obj, nil, 5) if err == nil { t.Errorf("Expecting error.") } }
func TestRESTClientRequires(t *testing.T) { if _, err := RESTClientFor(&Config{Host: "127.0.0.1", Version: "", Codec: testapi.Codec()}); err == nil { t.Errorf("unexpected non-error") } if _, err := RESTClientFor(&Config{Host: "127.0.0.1", Version: testapi.Version()}); err == nil { t.Errorf("unexpected non-error") } if _, err := RESTClientFor(&Config{Host: "127.0.0.1", Version: testapi.Version(), Codec: testapi.Codec()}); err != nil { t.Errorf("unexpected error: %v", err) } }
func TestDoRequestNewWayObj(t *testing.T) { reqObj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} reqBodyExpected, _ := testapi.Codec().Encode(reqObj) expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: util.NewIntOrStringFromInt(12345), }}}} expectedBody, _ := testapi.Codec().Encode(expectedObj) fakeHandler := util.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) c := NewOrDie(&Config{Host: testServer.URL, Version: testapi.Version(), Username: "******", Password: "******"}) obj, err := c.Verb("POST"). Suffix("baz"). Name("bar"). Resource("foo"). LabelsSelectorParam(labels.Set{"name": "foo"}.AsSelector()). Timeout(time.Second). Body(reqObj). Do().Get() if err != nil { t.Errorf("Unexpected error: %v %#v", err, err) return } if obj == nil { t.Error("nil obj") } else if !api.Semantic.DeepDerivative(expectedObj, obj) { t.Errorf("Expected: %#v, got %#v", expectedObj, obj) } tmpStr := string(reqBodyExpected) requestURL := testapi.ResourcePath("foo", "", "bar/baz") requestURL += "?" + api.LabelSelectorQueryParam(testapi.Version()) + "=name%3Dfoo&timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) if fakeHandler.RequestReceived.Header["Authorization"] == nil { t.Errorf("Request is missing authorization header: %#v", *fakeHandler.RequestReceived) } }
func TestExtractObj(t *testing.T) { fakeClient := NewFakeEtcdClient(t) helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix()) key := etcdtest.AddPrefix("/some/key") expect := api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyAlways, DNSPolicy: api.DNSClusterFirst, }, } fakeClient.Set(key, runtime.EncodeOrDie(testapi.Codec(), &expect), 0) var got api.Pod err := helper.ExtractObj("/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 TestStatusUpdatesWithoutReplicasChange(t *testing.T) { // Setup a fake server to listen for requests, and run the rc manager in steady state fakeHandler := util.FakeHandler{ StatusCode: 200, ResponseBody: "", } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady // Steady state for the replication controller, no Status.Replicas updates expected activePods := 5 rc := newReplicationController(activePods) manager.controllerStore.Store.Add(rc) rc.Status = api.ReplicationControllerStatus{Replicas: activePods} newPodList(manager.podStore.Store, activePods, api.PodRunning, rc) fakePodControl := FakePodControl{} manager.podControl = &fakePodControl manager.syncReplicationController(getKey(rc, t)) validateSyncReplication(t, &fakePodControl, 0, 0) if fakeHandler.RequestReceived != nil { t.Errorf("Unexpected update when pods and rcs are in a steady state") } // This response body is just so we don't err out decoding the http response, all // we care about is the request body sent below. response := runtime.EncodeOrDie(testapi.Codec(), &api.ReplicationController{}) fakeHandler.ResponseBody = response rc.Generation = rc.Generation + 1 manager.syncReplicationController(getKey(rc, t)) rc.Status.ObservedGeneration = rc.Generation updatedRc := runtime.EncodeOrDie(testapi.Codec(), rc) fakeHandler.ValidateRequest(t, testapi.ResourcePath(replicationControllerResourceName(), rc.Namespace, rc.Name), "PUT", &updatedRc) }
func TestControllerUpdateReplicas(t *testing.T) { // This is a happy server just to record the PUT request we expect for status.Replicas fakeHandler := util.FakeHandler{ StatusCode: 200, ResponseBody: "", } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady // Insufficient number of pods in the system, and Status.Replicas is wrong; // Status.Replica should update to match number of pods in system, 1 new pod should be created. rc := newReplicationController(5) manager.controllerStore.Store.Add(rc) rc.Status = api.ReplicationControllerStatus{Replicas: 2, ObservedGeneration: 0} rc.Generation = 1 newPodList(manager.podStore.Store, 4, api.PodRunning, rc) // This response body is just so we don't err out decoding the http response response := runtime.EncodeOrDie(testapi.Codec(), &api.ReplicationController{}) fakeHandler.ResponseBody = response fakePodControl := FakePodControl{} manager.podControl = &fakePodControl manager.syncReplicationController(getKey(rc, t)) // 1. Status.Replicas should go up from 2->4 even though we created 5-4=1 pod. // 2. Every update to the status should include the Generation of the spec. rc.Status = api.ReplicationControllerStatus{Replicas: 4, ObservedGeneration: 1} decRc := runtime.EncodeOrDie(testapi.Codec(), rc) fakeHandler.ValidateRequest(t, testapi.ResourcePath(replicationControllerResourceName(), rc.Namespace, rc.Name), "PUT", &decRc) validateSyncReplication(t, &fakePodControl, 1, 0) }
func makeTestServer(t *testing.T, namespace string, endpointsResponse serverResponse) (*httptest.Server, *util.FakeHandler) { fakeEndpointsHandler := util.FakeHandler{ StatusCode: endpointsResponse.statusCode, ResponseBody: runtime.EncodeOrDie(testapi.Codec(), endpointsResponse.obj.(runtime.Object)), } mux := http.NewServeMux() mux.Handle(testapi.ResourcePath("endpoints", namespace, ""), &fakeEndpointsHandler) mux.Handle(testapi.ResourcePath("endpoints/", namespace, ""), &fakeEndpointsHandler) mux.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) { t.Errorf("unexpected request: %v", req.RequestURI) res.WriteHeader(http.StatusNotFound) }) return httptest.NewServer(mux), &fakeEndpointsHandler }
func TestRequestStream(t *testing.T) { testCases := []struct { Request *Request Err bool }{ { Request: &Request{err: errors.New("bail")}, Err: true, }, { Request: &Request{baseURL: &url.URL{}, path: "%"}, Err: true, }, { Request: &Request{ client: clientFunc(func(req *http.Request) (*http.Response, error) { return nil, errors.New("err") }), baseURL: &url.URL{}, }, Err: true, }, { Request: &Request{ client: clientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusUnauthorized, Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(testapi.Codec(), &api.Status{ Status: api.StatusFailure, Reason: api.StatusReasonUnauthorized, })))), }, nil }), codec: latest.Codec, baseURL: &url.URL{}, }, Err: true, }, } for i, testCase := range testCases { body, err := testCase.Request.Stream() hasErr := err != nil if hasErr != testCase.Err { t.Errorf("%d: expected %t, got %t: %v", i, testCase.Err, hasErr, err) } if hasErr && body != nil { t.Errorf("%d: body should be nil when error is returned", i) } } }
func initialObject(ecli *tools.FakeEtcdClient) { ecli.Data[key()] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ CreatedIndex: 1, ModifiedIndex: 2, Value: runtime.EncodeOrDie(testapi.Codec(), &api.RangeAllocation{ Range: "rangeSpecValue", }), }, }, E: nil, } }
func initialObject(ecli *tools.FakeEtcdClient) { _, cidr, _ := net.ParseCIDR("192.168.1.0/24") ecli.Data[key()] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ CreatedIndex: 1, ModifiedIndex: 2, Value: runtime.EncodeOrDie(testapi.Codec(), &api.RangeAllocation{ Range: cidr.String(), }), }, }, E: nil, } }
func TestSetObjWithVersion(t *testing.T) { obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}} fakeClient := NewFakeEtcdClient(t) fakeClient.TestIndex = true helper := NewEtcdHelper(fakeClient, testapi.Codec(), etcdtest.PathPrefix()) key := etcdtest.AddPrefix("/some/key") fakeClient.Data[key] = EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: runtime.EncodeOrDie(testapi.Codec(), obj), ModifiedIndex: 1, }, }, } returnedObj := &api.Pod{} err := helper.SetObj("/some/key", obj, returnedObj, 7) if err != nil { t.Fatalf("Unexpected error %#v", err) } data, err := testapi.Codec().Encode(obj) if err != nil { t.Fatalf("Unexpected error %#v", err) } expect := string(data) got := fakeClient.Data[key].R.Node.Value if expect != got { t.Errorf("Wanted %v, got %v", expect, got) } if e, a := uint64(7), fakeClient.LastSetTTL; e != a { t.Errorf("Wanted %v, got %v", e, a) } if obj.ResourceVersion != returnedObj.ResourceVersion || obj.Name != returnedObj.Name { t.Errorf("If set was successful but returned object did not have correct resource version") } }
func TestEtcdWatch(t *testing.T) { table := map[string]generic.Matcher{ "single": setMatcher{util.NewStringSet("foo")}, "multi": setMatcher{util.NewStringSet("foo", "bar")}, } for name, m := range table { podA := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: api.NamespaceDefault, ResourceVersion: "1", }, Spec: api.PodSpec{NodeName: "machine"}, } respWithPodA := &etcd.Response{ Node: &etcd.Node{ Key: "/registry/pods/default/foo", Value: runtime.EncodeOrDie(testapi.Codec(), podA), ModifiedIndex: 1, CreatedIndex: 1, }, Action: "create", } fakeClient, registry := NewTestGenericEtcdRegistry(t) wi, err := registry.WatchPredicate(api.NewContext(), m, "1") if err != nil { t.Errorf("%v: unexpected error: %v", name, err) continue } fakeClient.WaitForWatchCompletion() go func() { fakeClient.WatchResponse <- respWithPodA }() got, open := <-wi.ResultChan() if !open { t.Errorf("%v: unexpected channel close", name) continue } if e, a := podA, got.Object; !api.Semantic.DeepDerivative(e, a) { t.Errorf("%v: difference: %s", name, util.ObjectDiff(e, a)) } } }
func TestSyncEndpointsItemsPreexistingLabelsChange(t *testing.T) { ns := "bar" testServer, endpointsHandler := makeTestServer(t, ns, serverResponse{http.StatusOK, &api.Endpoints{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, ResourceVersion: "1", Labels: map[string]string{ "foo": "bar", }, }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, Ports: []api.EndpointPort{{Port: 1000}}, }}, }}) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) endpoints := NewEndpointController(client) addPods(endpoints.podStore.Store, ns, 1, 1) serviceLabels := map[string]string{"baz": "blah"} endpoints.serviceStore.Store.Add(&api.Service{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, Labels: serviceLabels, }, Spec: api.ServiceSpec{ Selector: map[string]string{"foo": "bar"}, Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8080)}}, }, }) endpoints.syncService(ns + "/foo") data := runtime.EncodeOrDie(testapi.Codec(), &api.Endpoints{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, ResourceVersion: "1", Labels: serviceLabels, }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, }}, }) endpointsHandler.ValidateRequest(t, testapi.ResourcePath("endpoints", ns, "foo"), "PUT", &data) }
func TestSyncEndpointsItemsWithLabels(t *testing.T) { ns := "other" testServer, endpointsHandler := makeTestServer(t, ns, serverResponse{http.StatusOK, &api.Endpoints{}}) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) endpoints := NewEndpointController(client) addPods(endpoints.podStore.Store, ns, 3, 2) serviceLabels := map[string]string{"foo": "bar"} endpoints.serviceStore.Store.Add(&api.Service{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, Labels: serviceLabels, }, Spec: api.ServiceSpec{ Selector: map[string]string{"foo": "bar"}, Ports: []api.ServicePort{ {Name: "port0", Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8080)}, {Name: "port1", Port: 88, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8088)}, }, }, }) endpoints.syncService(ns + "/foo") expectedSubsets := []api.EndpointSubset{{ Addresses: []api.EndpointAddress{ {IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}, {IP: "1.2.3.5", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod1", Namespace: ns}}, {IP: "1.2.3.6", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod2", Namespace: ns}}, }, Ports: []api.EndpointPort{ {Name: "port0", Port: 8080, Protocol: "TCP"}, {Name: "port1", Port: 8088, Protocol: "TCP"}, }, }} data := runtime.EncodeOrDie(testapi.Codec(), &api.Endpoints{ ObjectMeta: api.ObjectMeta{ ResourceVersion: "", Labels: serviceLabels, }, Subsets: endptspkg.SortSubsets(expectedSubsets), }) // endpointsHandler should get 2 requests - one for "GET" and the next for "POST". endpointsHandler.ValidateRequestCount(t, 2) endpointsHandler.ValidateRequest(t, testapi.ResourcePath("endpoints", ns, ""), "POST", &data) }
func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { t := &testFactory{ Validator: validation.NullSchema{}, } generators := map[string]qingctl.Generator{ "run/v1": qingctl.BasicReplicationController{}, "service/v1": qingctl.ServiceGenerator{}, } return &cmdutil.Factory{ Object: func() (meta.RESTMapper, runtime.ObjectTyper) { return latest.RESTMapper, api.Scheme }, Client: func() (*client.Client, error) { // Swap out the HTTP client out of the client with the fake's version. fakeClient := t.Client.(*client.FakeRESTClient) c := client.NewOrDie(t.ClientConfig) c.Client = fakeClient.Client return c, t.Err }, RESTClient: func(*meta.RESTMapping) (resource.RESTClient, error) { return t.Client, t.Err }, Describer: func(*meta.RESTMapping) (qingctl.Describer, error) { return t.Describer, t.Err }, Printer: func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, columnLabels []string) (qingctl.ResourcePrinter, error) { return t.Printer, t.Err }, Validator: func() (validation.Schema, error) { return t.Validator, t.Err }, DefaultNamespace: func() (string, error) { return t.Namespace, t.Err }, ClientConfig: func() (*client.Config, error) { return t.ClientConfig, t.Err }, Generator: func(name string) (qingctl.Generator, bool) { generator, ok := generators[name] return generator, ok }, }, t, testapi.Codec() }