func TestEtcdDeletePod(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.TestIndex = true key := "/registry/pods/foo" fakeClient.Set(key, api.EncodeOrDie(api.Pod{ JSONBase: api.JSONBase{ID: "foo"}, DesiredState: api.PodState{Host: "machine"}, }), 0) fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(&api.ContainerManifestList{ Items: []api.ContainerManifest{ {ID: "foo"}, }, }), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) err := registry.DeletePod("foo") if err != nil { t.Errorf("unexpected error: %v", err) } if len(fakeClient.DeletedKeys) != 1 { t.Errorf("Expected 1 delete, found %#v", fakeClient.DeletedKeys) } else if fakeClient.DeletedKeys[0] != key { t.Errorf("Unexpected key: %s, expected %s", fakeClient.DeletedKeys[0], key) } response, err := fakeClient.Get("/registry/hosts/machine/kubelet", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var manifests api.ContainerManifestList api.DecodeInto([]byte(response.Node.Value), &manifests) if len(manifests.Items) != 0 { t.Errorf("Unexpected container set: %s, expected empty", response.Node.Value) } }
func TestEtcdListServices(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) key := "/registry/services/specs" fakeClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Nodes: []*etcd.Node{ { Value: api.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), }, { Value: api.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "bar"}}), }, }, }, }, E: nil, } registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) services, err := registry.ListServices() if err != nil { t.Errorf("unexpected error: %v", err) } if len(services.Items) != 2 || services.Items[0].ID != "foo" || services.Items[1].ID != "bar" { t.Errorf("Unexpected pod list: %#v", services) } }
func TestEtcdListControllers(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) key := "/registry/controllers" fakeClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Nodes: []*etcd.Node{ { Value: api.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), }, { Value: api.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "bar"}}), }, }, }, }, E: nil, } registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) controllers, err := registry.ListControllers() if err != nil { t.Errorf("unexpected error: %v", err) } if len(controllers) != 2 || controllers[0].ID != "foo" || controllers[1].ID != "bar" { t.Errorf("Unexpected controller list: %#v", controllers) } }
func TestWatchListFromZeroIndex(t *testing.T) { pod := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}} fakeClient := NewFakeEtcdClient(t) fakeClient.Data["/some/key"] = EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Dir: true, Nodes: etcd.Nodes{ &etcd.Node{ Value: api.EncodeOrDie(pod), CreatedIndex: 1, ModifiedIndex: 1, Nodes: etcd.Nodes{}, }, &etcd.Node{ Value: api.EncodeOrDie(pod), CreatedIndex: 2, ModifiedIndex: 2, Nodes: etcd.Nodes{}, }, }, }, Action: "get", EtcdIndex: 3, }, } h := EtcdHelper{fakeClient, codec, versioner} watching, err := h.WatchList("/some/key", 0, Everything) if err != nil { t.Fatalf("Unexpected error: %v", err) } // the existing node is detected and the index set event, open := <-watching.ResultChan() if !open { t.Fatalf("unexpected channel close") } for i := 0; i < 2; i++ { if e, a := watch.Added, event.Type; e != a { t.Errorf("Expected %v, got %v", e, a) } actualPod, ok := event.Object.(*api.Pod) if !ok { t.Fatalf("expected a pod, got %#v", event.Object) } if actualPod.ResourceVersion != 1 { t.Errorf("Expected pod with resource version %d, Got %#v", 1, actualPod) } pod.ResourceVersion = 1 if e, a := pod, event.Object; !reflect.DeepEqual(e, a) { t.Errorf("Expected %v, got %v", e, a) } } fakeClient.WaitForWatchCompletion() watching.Stop() }
func TestGetEtcd(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) ch := make(chan interface{}, 1) manifest := api.ContainerManifest{ID: "foo", Version: "v1beta1", Containers: []api.Container{{Name: "1", Image: "foo"}}} fakeClient.Data["/registry/hosts/machine/kubelet"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: api.EncodeOrDie(&api.ContainerManifestList{ Items: []api.ContainerManifest{manifest}, }), ModifiedIndex: 1, }, }, E: nil, } c := SourceEtcd{"/registry/hosts/machine/kubelet", fakeClient, ch, time.Millisecond} lastIndex, err := c.fetchNextState(0) if err != nil { t.Errorf("Unexpected error: %v", err) } if lastIndex != 2 { t.Errorf("Expected %#v, Got %#v", 2, lastIndex) } update := (<-ch).(kubelet.PodUpdate) expected := CreatePodUpdate(kubelet.SET, kubelet.Pod{Name: "foo", Manifest: manifest}) if !reflect.DeepEqual(expected, update) { t.Errorf("Expected %#v, Got %#v", expected, update) } for i := range update.Pods { if errs := kubelet.ValidatePod(&update.Pods[i]); len(errs) != 0 { t.Errorf("Expected no validation errors on %#v, Got %#v", update.Pods[i], errs) } } }
func TestWatchEtcd(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) ch := make(chan interface{}, 1) fakeClient.Data["/registry/hosts/machine/kubelet"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: api.EncodeOrDie(&api.ContainerManifestList{}), ModifiedIndex: 2, }, }, E: nil, } c := SourceEtcd{"/registry/hosts/machine/kubelet", fakeClient, ch, time.Millisecond, time.Minute} lastIndex, err := c.fetchNextState(1) if err != nil { t.Errorf("Unexpected error: %v", err) } if lastIndex != 3 { t.Errorf("Expected %d, Got %d", 3, lastIndex) } update := (<-ch).(kubelet.PodUpdate) expected := CreatePodUpdate(kubelet.SET) if !reflect.DeepEqual(expected, update) { t.Errorf("Expected %#v, Got %#v", expected, update) } }
func TestEtcdUpdateService(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.TestIndex = true resp, _ := fakeClient.Set("/registry/services/specs/foo", api.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) testService := api.Service{ JSONBase: api.JSONBase{ID: "foo", ResourceVersion: resp.Node.ModifiedIndex}, Labels: map[string]string{ "baz": "bar", }, Selector: map[string]string{ "baz": "bar", }, } err := registry.UpdateService(testService) if err != nil { t.Errorf("unexpected error: %v", err) } svc, err := registry.GetService("foo") if err != nil { t.Errorf("unexpected error: %v", err) } // Clear modified indices before the equality test. svc.ResourceVersion = 0 testService.ResourceVersion = 0 if !reflect.DeepEqual(*svc, testService) { t.Errorf("Unexpected service: got\n %#v\n, wanted\n %#v", svc, testService) } }
func TestPollMinions(t *testing.T) { table := []struct { minions []api.Minion }{ { minions: []api.Minion{ {JSONBase: api.JSONBase{ID: "foo"}}, {JSONBase: api.JSONBase{ID: "bar"}}, }, }, } for _, item := range table { ml := &api.MinionList{Items: item.minions} handler := util.FakeHandler{ StatusCode: 200, ResponseBody: api.EncodeOrDie(ml), T: t, } server := httptest.NewServer(&handler) cf := ConfigFactory{client.New(server.URL, nil)} ce, err := cf.pollMinions() if err != nil { t.Errorf("Unexpected error: %v", err) continue } handler.ValidateRequest(t, "/api/v1beta1/minions", "GET", nil) if e, a := len(item.minions), ce.Len(); e != a { t.Errorf("Expected %v, got %v", e, a) } } }
func TestEtcdUpdateEndpoints(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.TestIndex = true registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) endpoints := api.Endpoints{ JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"baz", "bar"}, } fakeClient.Set("/registry/services/endpoints/foo", api.EncodeOrDie(api.Endpoints{}), 0) err := registry.UpdateEndpoints(endpoints) if err != nil { t.Errorf("unexpected error: %v", err) } response, err := fakeClient.Get("/registry/services/endpoints/foo", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var endpointsOut api.Endpoints err = api.DecodeInto([]byte(response.Node.Value), &endpointsOut) if !reflect.DeepEqual(endpoints, endpointsOut) { t.Errorf("Unexpected endpoints: %#v, expected %#v", endpointsOut, endpoints) } }
func TestDefaultErrorFunc(t *testing.T) { testPod := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}} handler := util.FakeHandler{ StatusCode: 200, ResponseBody: api.EncodeOrDie(testPod), T: t, } mux := http.NewServeMux() // FakeHandler musn't be sent requests other than the one you want to test. mux.Handle("/api/v1beta1/pods/foo", &handler) server := httptest.NewServer(mux) factory := ConfigFactory{client.NewOrDie(server.URL, nil)} queue := cache.NewFIFO() errFunc := factory.makeDefaultErrorFunc(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("foo") if !exists { continue } handler.ValidateRequest(t, "/api/v1beta1/pods/foo", "GET", nil) if e, a := testPod, got; !reflect.DeepEqual(e, a) { t.Errorf("Expected %v, got %v", e, a) } break } }
func TestEtcdDeletePodMultipleContainers(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) key := "/registry/hosts/machine/pods/foo" fakeClient.Set(key, util.MakeJSONString(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0) fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(&api.ContainerManifestList{ Items: []api.ContainerManifest{ {ID: "foo"}, {ID: "bar"}, }, }), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) err := registry.DeletePod("foo") expectNoError(t, err) if len(fakeClient.DeletedKeys) != 1 { t.Errorf("Expected 1 delete, found %#v", fakeClient.DeletedKeys) } if fakeClient.DeletedKeys[0] != key { t.Errorf("Unexpected key: %s, expected %s", fakeClient.DeletedKeys[0], key) } response, err := fakeClient.Get("/registry/hosts/machine/kubelet", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var manifests api.ContainerManifestList api.DecodeInto([]byte(response.Node.Value), &manifests) if len(manifests.Items) != 1 { t.Fatalf("Unexpected manifest set: %#v, expected empty", manifests) } if manifests.Items[0].ID != "bar" { t.Errorf("Deleted wrong manifest: %#v", manifests) } }
func TestBind(t *testing.T) { table := []struct { binding *api.Binding }{ {binding: &api.Binding{PodID: "foo", Host: "foohost.kubernetes.mydomain.com"}}, } for _, item := range table { handler := util.FakeHandler{ StatusCode: 200, ResponseBody: "", T: t, } server := httptest.NewServer(&handler) client := client.NewOrDie(server.URL, nil) b := binder{client} if err := b.Bind(item.binding); err != nil { t.Errorf("Unexpected error: %v", err) continue } expectedBody := api.EncodeOrDie(item.binding) handler.ValidateRequest(t, "/api/v1beta1/bindings", "POST", &expectedBody) } }
func TestSetObjWithVersion(t *testing.T) { obj := api.Pod{JSONBase: api.JSONBase{ID: "foo", ResourceVersion: 1}} fakeClient := NewFakeEtcdClient(t) fakeClient.TestIndex = true fakeClient.Data["/some/key"] = EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: api.EncodeOrDie(obj), ModifiedIndex: 1, }, }, } helper := EtcdHelper{fakeClient, codec, versioner} err := helper.SetObj("/some/key", obj) if err != nil { t.Fatalf("Unexpected error %#v", err) } data, err := codec.Encode(obj) if err != nil { t.Fatalf("Unexpected error %#v", err) } expect := string(data) got := fakeClient.Data["/some/key"].R.Node.Value if expect != got { t.Errorf("Wanted %v, got %v", expect, got) } }
func TestGetEtcdData(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) ch := make(chan interface{}) fakeClient.Data["/registry/hosts/machine/kubelet"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: api.EncodeOrDie(&api.ContainerManifestList{ Items: []api.ContainerManifest{{ID: "foo"}}, }), ModifiedIndex: 1, }, }, E: nil, } NewSourceEtcd("/registry/hosts/machine/kubelet", fakeClient, time.Millisecond, ch) //TODO: update FakeEtcdClient.Watch to handle receiver=nil with a given index //returns an infinite stream of updates for i := 0; i < 2; i++ { update := (<-ch).(kubelet.PodUpdate) expected := CreatePodUpdate(kubelet.SET, kubelet.Pod{Name: "foo", Manifest: api.ContainerManifest{ID: "foo"}}) if !reflect.DeepEqual(expected, update) { t.Errorf("Expected %#v, Got %#v", expected, update) } } }
func TestGetEtcd(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) ch := make(chan interface{}, 1) fakeClient.Data["/registry/hosts/machine/kubelet"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: api.EncodeOrDie(&api.ContainerManifestList{ Items: []api.ContainerManifest{{ID: "foo"}}, }), ModifiedIndex: 1, }, }, E: nil, } c := SourceEtcd{"/registry/hosts/machine/kubelet", fakeClient, ch, time.Millisecond} lastIndex, err := c.fetchNextState(0) if err != nil { t.Errorf("Unexpected error: %v", err) } if lastIndex != 2 { t.Errorf("Expected %#v, Got %#v", 2, lastIndex) } update := (<-ch).(kubelet.PodUpdate) expected := CreatePodUpdate(kubelet.SET, kubelet.Pod{Name: "foo", Manifest: api.ContainerManifest{ID: "foo"}}) if !reflect.DeepEqual(expected, update) { t.Errorf("Expected %#v, Got %#v", expected, update) } }
func TestEtcdCreatePod(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) fakeClient.TestIndex = true fakeClient.Data["/registry/pods/foo"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: nil, }, E: tools.EtcdErrorNotFound, } fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(&api.ContainerManifestList{}), 0) registry := NewTestEtcdRegistry(fakeClient) err := registry.CreatePod(api.Pod{ JSONBase: api.JSONBase{ ID: "foo", }, DesiredState: api.PodState{ Manifest: api.ContainerManifest{ Containers: []api.Container{ { Name: "foo", }, }, }, }, }) if err != nil { t.Fatalf("unexpected error: %v", err) } // Suddenly, a wild scheduler appears: err = registry.ApplyBinding(&api.Binding{PodID: "foo", Host: "machine"}) if err != nil { t.Fatalf("unexpected error: %v", err) } resp, err := fakeClient.Get("/registry/pods/foo", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var pod api.Pod err = api.DecodeInto([]byte(resp.Node.Value), &pod) if err != nil { t.Errorf("unexpected error: %v", err) } if pod.ID != "foo" { t.Errorf("Unexpected pod: %#v %s", pod, resp.Node.Value) } var manifests api.ContainerManifestList resp, err = fakeClient.Get("/registry/hosts/machine/kubelet", false, false) if err != nil { t.Errorf("unexpected error: %v", err) } err = api.DecodeInto([]byte(resp.Node.Value), &manifests) if len(manifests.Items) != 1 || manifests.Items[0].ID != "foo" { t.Errorf("Unexpected manifest list: %#v", manifests) } }
func TestEtcdCreatePodWithExistingContainers(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.TestIndex = true fakeClient.Data["/registry/hosts/machine/pods/foo"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: nil, }, E: tools.EtcdErrorNotFound, } fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(api.ContainerManifestList{ Items: []api.ContainerManifest{ {ID: "bar"}, }, }), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) err := registry.CreatePod("machine", api.Pod{ JSONBase: api.JSONBase{ ID: "foo", }, DesiredState: api.PodState{ Manifest: api.ContainerManifest{ ID: "foo", Containers: []api.Container{ { Name: "foo", }, }, }, }, }) if err != nil { t.Errorf("unexpected error: %v", err) } resp, err := fakeClient.Get("/registry/hosts/machine/pods/foo", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var pod api.Pod err = api.DecodeInto([]byte(resp.Node.Value), &pod) if err != nil { t.Errorf("unexpected error: %v", err) } if pod.ID != "foo" { t.Errorf("Unexpected pod: %#v %s", pod, resp.Node.Value) } var manifests api.ContainerManifestList resp, err = fakeClient.Get("/registry/hosts/machine/kubelet", false, false) if err != nil { t.Errorf("unexpected error: %v", err) } err = api.DecodeInto([]byte(resp.Node.Value), &manifests) if len(manifests.Items) != 2 || manifests.Items[1].ID != "foo" { t.Errorf("Unexpected manifest list: %#v", manifests) } }
func TestEtcdCreateServiceAlreadyExisting(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.Set("/registry/services/specs/foo", api.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) err := registry.CreateService(api.Service{ JSONBase: api.JSONBase{ID: "foo"}, }) if !apiserver.IsAlreadyExists(err) { t.Errorf("expected already exists err, got %#v", err) } }
func TestWatch(t *testing.T) { client := newEtcdClient() helper := tools.EtcdHelper{Client: client, Codec: api.Codec, ResourceVersioner: api.ResourceVersioner} withEtcdKey(func(key string) { resp, err := client.Set(key, api.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "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) 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 != expectedVersion { 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 != expectedVersion { t.Errorf("expected version %d, got %#v", expectedVersion, pod) } }) }
func TestEtcdGetPod(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.Set("/registry/pods/foo", api.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) pod, err := registry.GetPod("foo") if err != nil { t.Errorf("unexpected error: %v", err) } if pod.ID != "foo" { t.Errorf("Unexpected pod: %#v", pod) } }
func TestEtcdGetController(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.Set("/registry/controllers/foo", api.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) ctrl, err := registry.GetController("foo") if err != nil { t.Errorf("unexpected error: %v", err) } if ctrl.ID != "foo" { t.Errorf("Unexpected controller: %#v", ctrl) } }
func TestEtcdGetService(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.Set("/registry/services/specs/foo", api.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) service, err := registry.GetService("foo") if err != nil { t.Errorf("unexpected error: %v", err) } if service.ID != "foo" { t.Errorf("Unexpected pod: %#v", service) } }
func TestEtcdListPods(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) key := "/registry/pods" fakeClient.Data[key] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Nodes: []*etcd.Node{ { Value: api.EncodeOrDie(api.Pod{ JSONBase: api.JSONBase{ID: "foo"}, DesiredState: api.PodState{Host: "machine"}, }), }, { Value: api.EncodeOrDie(api.Pod{ JSONBase: api.JSONBase{ID: "bar"}, DesiredState: api.PodState{Host: "machine"}, }), }, }, }, }, E: nil, } registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) pods, err := registry.ListPods(labels.Everything()) if err != nil { t.Errorf("unexpected error: %v", err) } if len(pods) != 2 || pods[0].ID != "foo" || pods[1].ID != "bar" { t.Errorf("Unexpected pod list: %#v", pods) } if pods[0].CurrentState.Host != "machine" || pods[1].CurrentState.Host != "machine" { t.Errorf("Failed to populate host name.") } }
func TestEtcdCreateControllerAlreadyExisting(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) fakeClient.Set("/registry/controllers/foo", api.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0) registry := NewTestEtcdRegistry(fakeClient) err := registry.CreateController(api.ReplicationController{ JSONBase: api.JSONBase{ ID: "foo", }, }) if !apiserver.IsAlreadyExists(err) { t.Errorf("expected already exists err, got %#v", err) } }
func TestEtcdGetEndpoints(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) registry := NewTestEtcdRegistry(fakeClient) endpoints := &api.Endpoints{ JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:34855"}, } fakeClient.Set("/registry/services/endpoints/foo", api.EncodeOrDie(endpoints), 0) got, err := registry.GetEndpoints("foo") if err != nil { t.Errorf("unexpected error: %v", err) } if e, a := endpoints, got; !reflect.DeepEqual(e, a) { t.Errorf("Unexpected endpoints: %#v, expected %#v", e, a) } }
func TestEtcdCreatePodAlreadyExisting(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.Data["/registry/pods/foo"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: api.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), }, }, E: nil, } registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) err := registry.CreatePod("machine", api.Pod{ JSONBase: api.JSONBase{ ID: "foo", }, }) if err == nil { t.Error("Unexpected non-error") } }
func TestWatchFromZeroIndex(t *testing.T) { pod := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}} fakeClient := MakeFakeEtcdClient(t) fakeClient.Data["/some/key"] = EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: api.EncodeOrDie(pod), ModifiedIndex: 1, }, Action: "compareAndSwap", EtcdIndex: 2, }, } h := EtcdHelper{fakeClient, codec, versioner} watching, err := h.Watch("/some/key", 0) if err != nil { t.Fatalf("Unexpected error: %v", err) } fakeClient.WaitForWatchCompletion() // the existing node is detected and the index set event := <-watching.ResultChan() if e, a := watch.Modified, event.Type; e != a { t.Errorf("Expected %v, got %v", e, a) } actualPod, ok := event.Object.(*api.Pod) if !ok { t.Fatalf("expected a pod, got %#v", event.Object) } if actualPod.ResourceVersion != 1 { t.Errorf("Expected pod with resource version %d, Got %#v", 1, actualPod) } pod.ResourceVersion = 1 if e, a := pod, event.Object; !reflect.DeepEqual(e, a) { t.Errorf("Expected %v, got %v", e, a) } watching.Stop() }
func TestEtcdUpdateController(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.TestIndex = true resp, _ := fakeClient.Set("/registry/controllers/foo", api.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) err := registry.UpdateController(api.ReplicationController{ JSONBase: api.JSONBase{ID: "foo", ResourceVersion: resp.Node.ModifiedIndex}, DesiredState: api.ReplicationControllerState{ Replicas: 2, }, }) if err != nil { t.Errorf("unexpected error: %v", err) } ctrl, err := registry.GetController("foo") if ctrl.DesiredState.Replicas != 2 { t.Errorf("Unexpected controller: %#v", ctrl) } }
func TestWatchFromZeroIndex(t *testing.T) { pod := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}} testCases := map[string]struct { Response EtcdResponseWithError ExpectedVersion uint64 ExpectedType watch.EventType }{ "get value created": { EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: api.EncodeOrDie(pod), CreatedIndex: 1, ModifiedIndex: 1, }, Action: "get", EtcdIndex: 2, }, }, 1, watch.Added, }, "get value modified": { EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value: api.EncodeOrDie(pod), CreatedIndex: 1, ModifiedIndex: 2, }, Action: "get", EtcdIndex: 3, }, }, 2, watch.Modified, }, } for k, testCase := range testCases { fakeClient := MakeFakeEtcdClient(t) fakeClient.Data["/some/key"] = testCase.Response h := EtcdHelper{fakeClient, codec, versioner} watching, err := h.Watch("/some/key", 0) if err != nil { t.Fatalf("%s: unexpected error: %v", k, err) } fakeClient.WaitForWatchCompletion() if e, a := testCase.Response.R.EtcdIndex+1, fakeClient.WatchIndex; e != a { t.Errorf("%s: expected watch index to be %d, got %d", k, e, a) } // the existing node is detected and the index set event := <-watching.ResultChan() if e, a := testCase.ExpectedType, event.Type; e != a { t.Errorf("%s: expected %v, got %v", k, e, a) } actualPod, ok := event.Object.(*api.Pod) if !ok { t.Fatalf("%s: expected a pod, got %#v", k, event.Object) } if actualPod.ResourceVersion != testCase.ExpectedVersion { t.Errorf("%s: expected pod with resource version %d, Got %#v", k, testCase.ExpectedVersion, actualPod) } pod.ResourceVersion = testCase.ExpectedVersion if e, a := pod, event.Object; !reflect.DeepEqual(e, a) { t.Errorf("%s: expected %v, got %v", k, e, a) } watching.Stop() } }
func TestWatchInterpretations(t *testing.T) { // Declare some pods to make the test cases compact. podFoo := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}} podBar := &api.Pod{JSONBase: api.JSONBase{ID: "bar"}} podBaz := &api.Pod{JSONBase: api.JSONBase{ID: "baz"}} firstLetterIsB := func(obj interface{}) bool { return obj.(*api.Pod).ID[0] == 'b' } // All of these test cases will be run with the firstLetterIsB FilterFunc. table := map[string]struct { actions []string // Run this test item for every action here. prevNodeValue string nodeValue string expectEmit bool expectType watch.EventType expectObject interface{} }{ "create": { actions: []string{"create", "get"}, nodeValue: api.EncodeOrDie(podBar), expectEmit: true, expectType: watch.Added, expectObject: podBar, }, "create but filter blocks": { actions: []string{"create", "get"}, nodeValue: api.EncodeOrDie(podFoo), expectEmit: false, }, "delete": { actions: []string{"delete"}, prevNodeValue: api.EncodeOrDie(podBar), expectEmit: true, expectType: watch.Deleted, expectObject: podBar, }, "delete but filter blocks": { actions: []string{"delete"}, nodeValue: api.EncodeOrDie(podFoo), expectEmit: false, }, "modify appears to create 1": { actions: []string{"set", "compareAndSwap"}, nodeValue: api.EncodeOrDie(podBar), expectEmit: true, expectType: watch.Added, expectObject: podBar, }, "modify appears to create 2": { actions: []string{"set", "compareAndSwap"}, prevNodeValue: api.EncodeOrDie(podFoo), nodeValue: api.EncodeOrDie(podBar), expectEmit: true, expectType: watch.Added, expectObject: podBar, }, "modify appears to delete": { actions: []string{"set", "compareAndSwap"}, prevNodeValue: api.EncodeOrDie(podBar), nodeValue: api.EncodeOrDie(podFoo), expectEmit: true, expectType: watch.Deleted, expectObject: podBar, // Should return last state that passed the filter! }, "modify modifies": { actions: []string{"set", "compareAndSwap"}, prevNodeValue: api.EncodeOrDie(podBar), nodeValue: api.EncodeOrDie(podBaz), expectEmit: true, expectType: watch.Modified, expectObject: podBaz, }, "modify ignores": { actions: []string{"set", "compareAndSwap"}, nodeValue: api.EncodeOrDie(podFoo), expectEmit: false, }, } for name, item := range table { for _, action := range item.actions { w := newEtcdWatcher(true, firstLetterIsB, codec, versioner, nil) emitCalled := false w.emit = func(event watch.Event) { emitCalled = true if !item.expectEmit { return } if e, a := item.expectType, event.Type; e != a { t.Errorf("'%v - %v': expected %v, got %v", name, action, e, a) } if e, a := item.expectObject, event.Object; !reflect.DeepEqual(e, a) { t.Errorf("'%v - %v': expected %v, got %v", name, action, e, a) } } var n, pn *etcd.Node if item.nodeValue != "" { n = &etcd.Node{Value: item.nodeValue} } if item.prevNodeValue != "" { pn = &etcd.Node{Value: item.prevNodeValue} } w.sendResult(&etcd.Response{ Action: action, Node: n, PrevNode: pn, }) if e, a := item.expectEmit, emitCalled; e != a { t.Errorf("'%v - %v': expected %v, got %v", name, action, e, a) } w.Stop() } } }