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)
	}
}
示例#4
0
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()
}
示例#5
0
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)
		}
	}
}
示例#6
0
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)
	}
}
示例#8
0
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)
	}
}
示例#10
0
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
	}
}
示例#11
0
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)
	}
}
示例#12
0
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)
	}
}
示例#13
0
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)
	}
}
示例#14
0
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)
		}
	}
}
示例#15
0
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)
	}
}
示例#16
0
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)
	}
}
示例#19
0
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.")
	}
}
示例#24
0
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)
	}
}
示例#25
0
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")
	}
}
示例#27
0
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)
	}
}
示例#29
0
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()
	}
}
示例#30
0
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()
		}
	}
}