func TestResourceNames(t *testing.T) { pods, svc := testData() b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), "/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &svc.Items[0]), })). NamespaceParam("test") test := &testVisitor{} if b.Do().Err() == nil { t.Errorf("unexpected non-error") } b.ResourceNames("pods", "foo", "services/baz") err := b.Do().Visit(test.Handle) if err != nil || len(test.Infos) != 2 { t.Fatalf("unexpected response: %v %#v", err, test.Infos) } if !reflect.DeepEqual(&pods.Items[0], test.Objects()[0]) { t.Errorf("unexpected object: \n%#v, expected: \n%#v", test.Objects()[0], &pods.Items[0]) } if !reflect.DeepEqual(&svc.Items[0], test.Objects()[1]) { t.Errorf("unexpected object: \n%#v, expected: \n%#v", test.Objects()[1], &svc.Items[0]) } }
func TestMultipleResourceByTheSameName(t *testing.T) { pods, svcs := testData() b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), "/namespaces/test/pods/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[1]), "/namespaces/test/services/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &svcs.Items[0]), "/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &svcs.Items[0]), })). NamespaceParam("test") test := &testVisitor{} singular := false if b.Do().Err() == nil { t.Errorf("unexpected non-error") } b.ResourceTypeOrNameArgs(true, "pods,services", "foo", "baz") err := b.Do().IntoSingular(&singular).Visit(test.Handle) if err != nil || singular || len(test.Infos) != 4 { t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) } if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &svcs.Items[0], &svcs.Items[0]}, test.Objects()) { t.Errorf("unexpected visited objects: %#v", test.Objects()) } if _, err := b.Do().ResourceMapping(); err == nil { t.Errorf("unexpected non-error") } }
func TestSelector(t *testing.T) { pods, svc := testData() labelKey := unversioned.LabelSelectorQueryParam(testapi.Default.Version()) b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), svc), })). SelectorParam("a=b"). NamespaceParam("test"). Flatten() test := &testVisitor{} singular := false if b.Do().Err() == nil { t.Errorf("unexpected non-error") } b.ResourceTypeOrNameArgs(true, "pods,service") err := b.Do().IntoSingular(&singular).Visit(test.Handle) if err != nil || singular || len(test.Infos) != 3 { t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) } if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &svc.Items[0]}, test.Objects()) { t.Errorf("unexpected visited objects: %#v", test.Objects()) } if _, err := b.Do().ResourceMapping(); err == nil { t.Errorf("unexpected non-error") } }
func TestListObjectWithDifferentVersions(t *testing.T) { pods, svc := testData() labelKey := unversioned.LabelSelectorQueryParam(testapi.Default.Version()) obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), svc), })). SelectorParam("a=b"). NamespaceParam("test"). ResourceTypeOrNameArgs(true, "pods,services"). Flatten(). Do().Object() if err != nil { t.Fatalf("unexpected error: %v", err) } list, ok := obj.(*api.List) if !ok { t.Fatalf("unexpected object: %#v", obj) } // resource version differs between type lists, so it's not possible to get a single version. if list.ResourceVersion != "" || len(list.Items) != 3 { t.Errorf("unexpected list: %#v", list) } }
func TestLatest(t *testing.T) { r, _, _ := streamTestData() newPod := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "13"}, } newPod2 := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "14"}, } newSvc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "15"}, } b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), newPod), "/namespaces/test/pods/bar": runtime.EncodeOrDie(testapi.Default.Codec(), newPod2), "/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), newSvc), })). NamespaceParam("other").Stream(r, "STDIN").Flatten().Latest() test := &testVisitor{} singular := false err := b.Do().IntoSingular(&singular).Visit(test.Handle) if err != nil || singular || len(test.Infos) != 3 { t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) } if !api.Semantic.DeepDerivative([]runtime.Object{newPod, newPod2, newSvc}, test.Objects()) { t.Errorf("unexpected visited objects: %#v", test.Objects()) } }
func streamTestData() (io.Reader, *api.PodList, *api.ServiceList) { pods, svc := testData() r, w := io.Pipe() go func() { defer w.Close() w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), pods))) w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), svc))) }() return r, pods, svc }
func TestStore(t *testing.T) { fakeClient, storage, backing := newStorage(t) if _, err := fakeClient.Set(key(), runtime.EncodeOrDie(testapi.Default.Codec(), validNewRangeAllocation()), 0); err != nil { t.Fatalf("unexpected error: %v", err) } if err := storage.Allocate(net.ParseIP("192.168.1.2")); err != nil { t.Fatal(err) } ok, err := backing.Allocate(1) if err != nil { t.Fatal(err) } if ok { t.Fatal("Expected allocation to fail") } if err := storage.Allocate(net.ParseIP("192.168.1.2")); err != ipallocator.ErrAllocated { t.Fatal(err) } obj := fakeClient.Data[key()] if obj.R == nil || obj.R.Node == nil { t.Fatalf("%s is empty: %#v", key(), obj) } t.Logf("data: %#v", obj.R.Node) }
func TestUpdate(t *testing.T) { storage, fakeClient := newStorage(t) ctx := api.WithNamespace(api.NewContext(), "test") key := etcdtest.AddPrefix("/controllers/test/foo") if _, err := fakeClient.Set(key, runtime.EncodeOrDie(testapi.Default.Codec(), &validController), 0); err != nil { t.Fatalf("unexpected error: %v", err) } replicas := 12 update := extensions.Scale{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test"}, Spec: extensions.ScaleSpec{ Replicas: replicas, }, } if _, _, err := storage.Update(ctx, &update); err != nil { t.Fatalf("unexpected error: %v", err) } response, err := fakeClient.Get(key, false, false) if err != nil { t.Fatalf("unexpected error: %v", err) } var controller api.ReplicationController testapi.Extensions.Codec().DecodeInto([]byte(response.Node.Value), &controller) if controller.Spec.Replicas != replicas { t.Errorf("wrong replicas count expected: %d got: %d", replicas, controller.Spec.Replicas) } }
func TestNamespaceOverride(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) })) defer s.Close() b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). FilenameParam(false, s.URL). NamespaceParam("test") test := &testVisitor{} err := b.Do().Visit(test.Handle) if err != nil || len(test.Infos) != 1 && test.Infos[0].Namespace != "foo" { t.Fatalf("unexpected response: %v %#v", err, test.Infos) } b = NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). FilenameParam(true, s.URL). NamespaceParam("test") test = &testVisitor{} err = b.Do().Visit(test.Handle) if err == nil { t.Fatalf("expected namespace error. got: %#v", test.Infos) } }
func TestStorageError(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) prefixedKey := etcdtest.AddPrefix("pods") fakeClient.ExpectNotFoundGet(prefixedKey) cacher := newTestCacher(fakeClient) fakeClient.WaitForWatchCompletion() podFoo := makeTestPod("foo") // Set up Watch for object "podFoo". watcher, err := cacher.Watch(context.TODO(), "pods/ns/foo", 1, storage.Everything) if err != nil { t.Fatalf("unexpected error: %v", err) } fakeClient.WatchResponse <- &etcd.Response{ Action: "create", Node: &etcd.Node{ Value: string(runtime.EncodeOrDie(testapi.Default.Codec(), podFoo)), CreatedIndex: 1, ModifiedIndex: 1, }, } _ = <-watcher.ResultChan() // Injecting error is simulating error from etcd. // This is almost the same what would happen e.g. in case of // "error too old" when reconnecting to etcd watch. fakeClient.WatchInjectError <- fmt.Errorf("fake error") _, ok := <-watcher.ResultChan() if ok { t.Errorf("unexpected event") } }
func TestNodeBuilder(t *testing.T) { node := &api.Node{ ObjectMeta: api.ObjectMeta{Name: "node1", Namespace: "should-not-have", ResourceVersion: "10"}, Spec: api.NodeSpec{}, Status: api.NodeStatus{ Capacity: api.ResourceList{ api.ResourceCPU: resource.MustParse("1000m"), api.ResourceMemory: resource.MustParse("1Mi"), }, }, } r, w := io.Pipe() go func() { defer w.Close() w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), node))) }() b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). NamespaceParam("test").Stream(r, "STDIN") test := &testVisitor{} err := b.Do().Visit(test.Handle) if err != nil || len(test.Infos) != 1 { t.Fatalf("unexpected response: %v %#v", err, test.Infos) } info := test.Infos[0] if info.Name != "node1" || info.Namespace != "" || info.Object == nil { t.Errorf("unexpected info: %#v", info) } }
func TestScaleUpdate(t *testing.T) { storage, fakeClient := newStorage(t) ctx := api.WithNamespace(api.NewContext(), namespace) key := etcdtest.AddPrefix("/deployments/" + namespace + "/" + name) if _, err := fakeClient.Set(key, runtime.EncodeOrDie(testapi.Extensions.Codec(), &validDeployment), 0); err != nil { t.Fatalf("unexpected error: %v", err) } replicas := 12 update := extensions.Scale{ ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespace}, Spec: extensions.ScaleSpec{ Replicas: replicas, }, } if _, _, err := storage.Scale.Update(ctx, &update); err != nil { t.Fatalf("unexpected error: %v", err) } response, err := fakeClient.Get(key, false, false) if err != nil { t.Fatalf("unexpected error: %v", err) } var deployment extensions.Deployment testapi.Extensions.Codec().DecodeInto([]byte(response.Node.Value), &deployment) if deployment.Spec.Replicas != replicas { t.Errorf("wrong replicas count expected: %d got: %d", replicas, deployment.Spec.Replicas) } }
func TestListObject(t *testing.T) { pods, _ := testData() labelKey := unversioned.LabelSelectorQueryParam(testapi.Default.Version()) b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), })). SelectorParam("a=b"). NamespaceParam("test"). ResourceTypeOrNameArgs(true, "pods"). Flatten() obj, err := b.Do().Object() if err != nil { t.Fatalf("unexpected error: %v", err) } list, ok := obj.(*api.List) if !ok { t.Fatalf("unexpected object: %#v", obj) } if list.ResourceVersion != pods.ResourceVersion || len(list.Items) != 2 { t.Errorf("unexpected list: %#v", list) } mapping, err := b.Do().ResourceMapping() if err != nil { t.Fatalf("unexpected error: %v", err) } if mapping.Resource != "pods" { t.Errorf("unexpected resource mapping: %#v", mapping) } }
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.Default.Codec(), podA), ModifiedIndex: 1, CreatedIndex: 1, }, }, E: nil, } emptyNode := tools.EtcdResponseWithError{ R: &etcd.Response{}, E: tools.EtcdErrorNotFound, } testContext := api.WithNamespace(api.NewContext(), "test") 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(testContext, 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 (t *Tester) setObjectsForList(objects []runtime.Object) []runtime.Object { result := make([]runtime.Object, len(objects)) key := etcdtest.AddPrefix(t.storage.KeyRootFunc(t.tester.TestContext())) if len(objects) > 0 { nodes := make([]*etcd.Node, len(objects)) for i, obj := range objects { codec, _ := getCodec(obj) encoded := runtime.EncodeOrDie(codec, obj) decoded, _ := codec.Decode([]byte(encoded)) nodes[i] = &etcd.Node{Value: encoded} result[i] = decoded } t.fakeClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Nodes: nodes, }, }, E: nil, } } else { t.fakeClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{}, E: t.fakeClient.NewError(tools.EtcdErrorCodeNotFound), } } return result }
func TestBind(t *testing.T) { table := []struct { binding *api.Binding }{ {binding: &api.Binding{ ObjectMeta: api.ObjectMeta{ Namespace: api.NamespaceDefault, Name: "foo", }, Target: api.ObjectReference{ Name: "foohost.kubernetes.mydomain.com", }, }}, } for _, item := range table { handler := util.FakeHandler{ StatusCode: 200, ResponseBody: "", T: t, } server := httptest.NewServer(&handler) defer server.Close() client := client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Default.Version()}) b := binder{client} if err := b.Bind(item.binding); err != nil { t.Errorf("Unexpected error: %v", err) continue } expectedBody := runtime.EncodeOrDie(testapi.Default.Codec(), item.binding) handler.ValidateRequest(t, testapi.Default.ResourcePath("bindings", api.NamespaceDefault, ""), "POST", &expectedBody) } }
func TestResourceByNameAndEmptySelector(t *testing.T) { pods, _ := testData() b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), })). NamespaceParam("test"). SelectorParam(""). ResourceTypeOrNameArgs(true, "pods", "foo") singular := false infos, err := b.Do().IntoSingular(&singular).Infos() if err != nil || !singular || len(infos) != 1 { t.Fatalf("unexpected response: %v %t %#v", err, singular, infos) } if !reflect.DeepEqual(&pods.Items[0], infos[0].Object) { t.Errorf("unexpected object: %#v", infos[0]) } mapping, err := b.Do().ResourceMapping() if err != nil { t.Fatalf("unexpected error: %v", err) } if mapping.Resource != "pods" { t.Errorf("unexpected resource mapping: %#v", mapping) } }
func streamTestObject(obj runtime.Object) io.Reader { r, w := io.Pipe() go func() { defer w.Close() w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), obj))) }() return r }
func NewTestServer(t *testing.T, namespace string, mockPodListWatch *MockPodsListWatch) *TestServer { ts := TestServer{ stats: map[string]uint{}, } mux := http.NewServeMux() mux.HandleFunc(testapi.Default.ResourcePath("pods", namespace, ""), func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) pods := mockPodListWatch.Pods() w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &pods))) }) podsPrefix := testapi.Default.ResourcePath("pods", namespace, "") + "/" mux.HandleFunc(podsPrefix, func(w http.ResponseWriter, r *http.Request) { name := r.URL.Path[len(podsPrefix):] // update statistics for this pod ts.lock.Lock() defer ts.lock.Unlock() ts.stats[name] = ts.stats[name] + 1 p := mockPodListWatch.GetPod(name) if p != nil { w.WriteHeader(http.StatusOK) w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), p))) return } w.WriteHeader(http.StatusNotFound) }) mux.HandleFunc(testapi.Default.ResourcePath("events", namespace, ""), func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) mux.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) { t.Errorf("unexpected request: %v", req.RequestURI) res.WriteHeader(http.StatusNotFound) }) ts.server = httptest.NewServer(mux) return &ts }
func TestWatch(t *testing.T) { client := framework.NewEtcdClient() etcdStorage := etcd.NewEtcdStorage(client, testapi.Default.Codec(), etcdtest.PathPrefix()) framework.WithEtcdKey(func(key string) { key = etcdtest.AddPrefix(key) resp, err := client.Set(key, runtime.EncodeOrDie(testapi.Default.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 := etcdStorage.Watch(key, 0, storage.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 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.Default.Version()}) manager := NewReplicationManager(client, controller.NoResyncPeriodFunc, BurstReplicas) manager.podStoreSynced = alwaysReady // Steady state for the replication controller, no Status.Replicas updates expected activePods := 5 rc := newReplicationController(activePods) manager.rcStore.Store.Add(rc) rc.Status = api.ReplicationControllerStatus{Replicas: activePods} newPodList(manager.podStore.Store, activePods, api.PodRunning, rc) fakePodControl := controller.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.Default.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.Default.Codec(), rc) fakeHandler.ValidateRequest(t, testapi.Default.ResourcePath(replicationControllerResourceName(), rc.Namespace, rc.Name)+"/status", "PUT", &updatedRc) }
func TestStore(t *testing.T) { storage, fakeClient, backing := newStorage(t) if _, err := fakeClient.Set(key(), runtime.EncodeOrDie(testapi.Default.Codec(), validNewRangeAllocation()), 0); err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := storage.Allocate(2); err != nil { t.Fatal(err) } ok, err := backing.Allocate(2) if err != nil { t.Fatal(err) } if ok { t.Fatal("Expected backing allocation to fail") } if ok, err := storage.Allocate(2); ok || err != nil { t.Fatal("Expected allocation to fail") } obj := fakeClient.Data[key()] if obj.R == nil || obj.R.Node == nil { t.Fatalf("%s is empty: %#v", key(), obj) } t.Logf("data: %#v", obj.R.Node) other := allocator.NewAllocationMap(100, "rangeSpecValue") allocation := &api.RangeAllocation{} if err := storage.storage.Get(key(), allocation, false); err != nil { t.Fatal(err) } if allocation.ResourceVersion != "2" { t.Fatalf("%#v", allocation) } if allocation.Range != "rangeSpecValue" { t.Errorf("unexpected stored Range: %s", allocation.Range) } if err := other.Restore("rangeSpecValue", allocation.Data); err != nil { t.Fatal(err) } if !other.Has(2) { t.Fatalf("could not restore allocated IP: %#v", other) } other = allocator.NewAllocationMap(100, "rangeSpecValue") otherStorage := NewEtcd(other, "/ranges/serviceips", "serviceipallocation", storage.storage) if ok, err := otherStorage.Allocate(2); ok || err != nil { t.Fatal(err) } }
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.Default.Version()}) manager := NewReplicationManager(client, controller.NoResyncPeriodFunc, 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.rcStore.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.Default.Codec(), &api.ReplicationController{}) fakeHandler.ResponseBody = response fakePodControl := controller.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.Default.Codec(), rc) fakeHandler.ValidateRequest(t, testapi.Default.ResourcePath(replicationControllerResourceName(), rc.Namespace, rc.Name)+"/status", "PUT", &decRc) validateSyncReplication(t, &fakePodControl, 1, 0) }
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.Default.Codec(), &unversioned.Status{ Status: unversioned.StatusFailure, Reason: unversioned.StatusReasonUnauthorized, })))), }, nil }), codec: testapi.Default.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 makeTestServer(t *testing.T, namespace string, endpointsResponse serverResponse) (*httptest.Server, *util.FakeHandler) { fakeEndpointsHandler := util.FakeHandler{ StatusCode: endpointsResponse.statusCode, ResponseBody: runtime.EncodeOrDie(testapi.Default.Codec(), endpointsResponse.obj.(runtime.Object)), } mux := http.NewServeMux() mux.Handle(testapi.Default.ResourcePath("endpoints", namespace, ""), &fakeEndpointsHandler) mux.Handle(testapi.Default.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 TestReceiveMultipleErrors(t *testing.T) { pods, svc := testData() r, w := io.Pipe() go func() { defer w.Close() w.Write([]byte(`{}`)) w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]))) }() r2, w2 := io.Pipe() go func() { defer w2.Close() w2.Write([]byte(`{}`)) w2.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &svc.Items[0]))) }() b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). Stream(r, "1").Stream(r2, "2"). ContinueOnError() test := &testVisitor{} singular := false err := b.Do().IntoSingular(&singular).Visit(test.Handle) if err == nil || singular || len(test.Infos) != 2 { t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) } errs, ok := err.(utilerrors.Aggregate) if !ok { t.Fatalf("unexpected error: %v", reflect.TypeOf(err)) } if len(errs.Errors()) != 2 { t.Errorf("unexpected errors %v", errs) } }
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 TestDefaultErrorFunc(t *testing.T) { grace := int64(30) testPod := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyAlways, DNSPolicy: api.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, }, } 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) defer server.Close() factory := NewConfigFactory(client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Default.Version()}), nil) 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 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.Default.Version()}) endpoints := NewEndpointController(client, controller.NoResyncPeriodFunc) addPods(endpoints.podStore.Store, ns, 1, 1, 0) 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.Default.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.Default.ResourcePath("endpoints", ns, "foo"), "PUT", &data) }
func main() { flag.Parse() if *kubeconfig == "" { log.Fatalf("Need to specify --kubeconfig") } cfg := read(*kubeconfig) secret := &api.Secret{ ObjectMeta: api.ObjectMeta{ Name: *name, Namespace: *ns, }, Data: map[string][]byte{ "config": cfg, }, } fmt.Printf(runtime.EncodeOrDie(latest.GroupOrDie("").Codec, secret)) }