github.com/deemoprobe/k8s-first-commit@v0.0.0-20230430165612-a541f1982be3/pkg/registry/etcd_registry_test.go (about)

     1  /*
     2  Copyright 2014 Google Inc. All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  package registry
    17  
    18  import (
    19  	"encoding/json"
    20  	"reflect"
    21  	"testing"
    22  
    23  	. "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
    24  	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
    25  	"github.com/coreos/go-etcd/etcd"
    26  )
    27  
    28  func TestEtcdGetTask(t *testing.T) {
    29  	fakeClient := MakeFakeEtcdClient(t)
    30  	fakeClient.Set("/registry/hosts/machine/tasks/foo", util.MakeJSONString(Task{JSONBase: JSONBase{ID: "foo"}}), 0)
    31  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
    32  	task, err := registry.GetTask("foo")
    33  	expectNoError(t, err)
    34  	if task.ID != "foo" {
    35  		t.Errorf("Unexpected task: %#v", task)
    36  	}
    37  }
    38  
    39  func TestEtcdGetTaskNotFound(t *testing.T) {
    40  	fakeClient := MakeFakeEtcdClient(t)
    41  	fakeClient.Data["/registry/hosts/machine/tasks/foo"] = EtcdResponseWithError{
    42  		R: &etcd.Response{
    43  			Node: nil,
    44  		},
    45  		E: &etcd.EtcdError{
    46  			ErrorCode: 100,
    47  		},
    48  	}
    49  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
    50  	_, err := registry.GetTask("foo")
    51  	if err == nil {
    52  		t.Errorf("Unexpected non-error.")
    53  	}
    54  }
    55  
    56  func TestEtcdCreateTask(t *testing.T) {
    57  	fakeClient := MakeFakeEtcdClient(t)
    58  	fakeClient.Data["/registry/hosts/machine/tasks/foo"] = EtcdResponseWithError{
    59  		R: &etcd.Response{
    60  			Node: nil,
    61  		},
    62  		E: &etcd.EtcdError{ErrorCode: 100},
    63  	}
    64  	fakeClient.Set("/registry/hosts/machine/kubelet", util.MakeJSONString([]ContainerManifest{}), 0)
    65  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
    66  	err := registry.CreateTask("machine", Task{
    67  		JSONBase: JSONBase{
    68  			ID: "foo",
    69  		},
    70  		DesiredState: TaskState{
    71  			Manifest: ContainerManifest{
    72  				Containers: []Container{
    73  					Container{
    74  						Name: "foo",
    75  					},
    76  				},
    77  			},
    78  		},
    79  	})
    80  	expectNoError(t, err)
    81  	resp, err := fakeClient.Get("/registry/hosts/machine/tasks/foo", false, false)
    82  	expectNoError(t, err)
    83  	var task Task
    84  	err = json.Unmarshal([]byte(resp.Node.Value), &task)
    85  	expectNoError(t, err)
    86  	if task.ID != "foo" {
    87  		t.Errorf("Unexpected task: %#v %s", task, resp.Node.Value)
    88  	}
    89  	var manifests []ContainerManifest
    90  	resp, err = fakeClient.Get("/registry/hosts/machine/kubelet", false, false)
    91  	expectNoError(t, err)
    92  	err = json.Unmarshal([]byte(resp.Node.Value), &manifests)
    93  	if len(manifests) != 1 || manifests[0].Id != "foo" {
    94  		t.Errorf("Unexpected manifest list: %#v", manifests)
    95  	}
    96  }
    97  
    98  func TestEtcdCreateTaskAlreadyExisting(t *testing.T) {
    99  	fakeClient := MakeFakeEtcdClient(t)
   100  	fakeClient.Data["/registry/hosts/machine/tasks/foo"] = EtcdResponseWithError{
   101  		R: &etcd.Response{
   102  			Node: &etcd.Node{
   103  				Value: util.MakeJSONString(Task{JSONBase: JSONBase{ID: "foo"}}),
   104  			},
   105  		},
   106  		E: nil,
   107  	}
   108  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   109  	err := registry.CreateTask("machine", Task{
   110  		JSONBase: JSONBase{
   111  			ID: "foo",
   112  		},
   113  	})
   114  	if err == nil {
   115  		t.Error("Unexpected non-error")
   116  	}
   117  }
   118  
   119  func TestEtcdCreateTaskWithContainersError(t *testing.T) {
   120  	fakeClient := MakeFakeEtcdClient(t)
   121  	fakeClient.Data["/registry/hosts/machine/tasks/foo"] = EtcdResponseWithError{
   122  		R: &etcd.Response{
   123  			Node: nil,
   124  		},
   125  		E: &etcd.EtcdError{ErrorCode: 100},
   126  	}
   127  	fakeClient.Data["/registry/hosts/machine/kubelet"] = EtcdResponseWithError{
   128  		R: &etcd.Response{
   129  			Node: nil,
   130  		},
   131  		E: &etcd.EtcdError{ErrorCode: 200},
   132  	}
   133  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   134  	err := registry.CreateTask("machine", Task{
   135  		JSONBase: JSONBase{
   136  			ID: "foo",
   137  		},
   138  	})
   139  	if err == nil {
   140  		t.Error("Unexpected non-error")
   141  	}
   142  	_, err = fakeClient.Get("/registry/hosts/machine/tasks/foo", false, false)
   143  	if err == nil {
   144  		t.Error("Unexpected non-error")
   145  	}
   146  	if err != nil && err.(*etcd.EtcdError).ErrorCode != 100 {
   147  		t.Errorf("Unexpected error: %#v", err)
   148  	}
   149  }
   150  
   151  func TestEtcdCreateTaskWithContainersNotFound(t *testing.T) {
   152  	fakeClient := MakeFakeEtcdClient(t)
   153  	fakeClient.Data["/registry/hosts/machine/tasks/foo"] = EtcdResponseWithError{
   154  		R: &etcd.Response{
   155  			Node: nil,
   156  		},
   157  		E: &etcd.EtcdError{ErrorCode: 100},
   158  	}
   159  	fakeClient.Data["/registry/hosts/machine/kubelet"] = EtcdResponseWithError{
   160  		R: &etcd.Response{
   161  			Node: nil,
   162  		},
   163  		E: &etcd.EtcdError{ErrorCode: 100},
   164  	}
   165  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   166  	err := registry.CreateTask("machine", Task{
   167  		JSONBase: JSONBase{
   168  			ID: "foo",
   169  		},
   170  		DesiredState: TaskState{
   171  			Manifest: ContainerManifest{
   172  				Id: "foo",
   173  				Containers: []Container{
   174  					Container{
   175  						Name: "foo",
   176  					},
   177  				},
   178  			},
   179  		},
   180  	})
   181  	expectNoError(t, err)
   182  	resp, err := fakeClient.Get("/registry/hosts/machine/tasks/foo", false, false)
   183  	expectNoError(t, err)
   184  	var task Task
   185  	err = json.Unmarshal([]byte(resp.Node.Value), &task)
   186  	expectNoError(t, err)
   187  	if task.ID != "foo" {
   188  		t.Errorf("Unexpected task: %#v %s", task, resp.Node.Value)
   189  	}
   190  	var manifests []ContainerManifest
   191  	resp, err = fakeClient.Get("/registry/hosts/machine/kubelet", false, false)
   192  	expectNoError(t, err)
   193  	err = json.Unmarshal([]byte(resp.Node.Value), &manifests)
   194  	if len(manifests) != 1 || manifests[0].Id != "foo" {
   195  		t.Errorf("Unexpected manifest list: %#v", manifests)
   196  	}
   197  }
   198  
   199  func TestEtcdCreateTaskWithExistingContainers(t *testing.T) {
   200  	fakeClient := MakeFakeEtcdClient(t)
   201  	fakeClient.Data["/registry/hosts/machine/tasks/foo"] = EtcdResponseWithError{
   202  		R: &etcd.Response{
   203  			Node: nil,
   204  		},
   205  		E: &etcd.EtcdError{ErrorCode: 100},
   206  	}
   207  	fakeClient.Set("/registry/hosts/machine/kubelet", util.MakeJSONString([]ContainerManifest{
   208  		ContainerManifest{
   209  			Id: "bar",
   210  		},
   211  	}), 0)
   212  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   213  	err := registry.CreateTask("machine", Task{
   214  		JSONBase: JSONBase{
   215  			ID: "foo",
   216  		},
   217  		DesiredState: TaskState{
   218  			Manifest: ContainerManifest{
   219  				Id: "foo",
   220  				Containers: []Container{
   221  					Container{
   222  						Name: "foo",
   223  					},
   224  				},
   225  			},
   226  		},
   227  	})
   228  	expectNoError(t, err)
   229  	resp, err := fakeClient.Get("/registry/hosts/machine/tasks/foo", false, false)
   230  	expectNoError(t, err)
   231  	var task Task
   232  	err = json.Unmarshal([]byte(resp.Node.Value), &task)
   233  	expectNoError(t, err)
   234  	if task.ID != "foo" {
   235  		t.Errorf("Unexpected task: %#v %s", task, resp.Node.Value)
   236  	}
   237  	var manifests []ContainerManifest
   238  	resp, err = fakeClient.Get("/registry/hosts/machine/kubelet", false, false)
   239  	expectNoError(t, err)
   240  	err = json.Unmarshal([]byte(resp.Node.Value), &manifests)
   241  	if len(manifests) != 2 || manifests[1].Id != "foo" {
   242  		t.Errorf("Unexpected manifest list: %#v", manifests)
   243  	}
   244  }
   245  
   246  func TestEtcdDeleteTask(t *testing.T) {
   247  	fakeClient := MakeFakeEtcdClient(t)
   248  	key := "/registry/hosts/machine/tasks/foo"
   249  	fakeClient.Set(key, util.MakeJSONString(Task{JSONBase: JSONBase{ID: "foo"}}), 0)
   250  	fakeClient.Set("/registry/hosts/machine/kubelet", util.MakeJSONString([]ContainerManifest{
   251  		ContainerManifest{
   252  			Id: "foo",
   253  		},
   254  	}), 0)
   255  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   256  	err := registry.DeleteTask("foo")
   257  	expectNoError(t, err)
   258  	if len(fakeClient.deletedKeys) != 1 {
   259  		t.Errorf("Expected 1 delete, found %#v", fakeClient.deletedKeys)
   260  	}
   261  	if fakeClient.deletedKeys[0] != key {
   262  		t.Errorf("Unexpected key: %s, expected %s", fakeClient.deletedKeys[0], key)
   263  	}
   264  	response, _ := fakeClient.Get("/registry/hosts/machine/kubelet", false, false)
   265  	if response.Node.Value != "[]" {
   266  		t.Errorf("Unexpected container set: %s, expected empty", response.Node.Value)
   267  	}
   268  }
   269  
   270  func TestEtcdDeleteTaskMultipleContainers(t *testing.T) {
   271  	fakeClient := MakeFakeEtcdClient(t)
   272  	key := "/registry/hosts/machine/tasks/foo"
   273  	fakeClient.Set(key, util.MakeJSONString(Task{JSONBase: JSONBase{ID: "foo"}}), 0)
   274  	fakeClient.Set("/registry/hosts/machine/kubelet", util.MakeJSONString([]ContainerManifest{
   275  		ContainerManifest{Id: "foo"},
   276  		ContainerManifest{Id: "bar"},
   277  	}), 0)
   278  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   279  	err := registry.DeleteTask("foo")
   280  	expectNoError(t, err)
   281  	if len(fakeClient.deletedKeys) != 1 {
   282  		t.Errorf("Expected 1 delete, found %#v", fakeClient.deletedKeys)
   283  	}
   284  	if fakeClient.deletedKeys[0] != key {
   285  		t.Errorf("Unexpected key: %s, expected %s", fakeClient.deletedKeys[0], key)
   286  	}
   287  	response, _ := fakeClient.Get("/registry/hosts/machine/kubelet", false, false)
   288  	var manifests []ContainerManifest
   289  	json.Unmarshal([]byte(response.Node.Value), &manifests)
   290  	if len(manifests) != 1 {
   291  		t.Errorf("Unexpected manifest set: %#v, expected empty", manifests)
   292  	}
   293  	if manifests[0].Id != "bar" {
   294  		t.Errorf("Deleted wrong manifest: %#v", manifests)
   295  	}
   296  }
   297  
   298  func TestEtcdEmptyListTasks(t *testing.T) {
   299  	fakeClient := MakeFakeEtcdClient(t)
   300  	key := "/registry/hosts/machine/tasks"
   301  	fakeClient.Data[key] = EtcdResponseWithError{
   302  		R: &etcd.Response{
   303  			Node: &etcd.Node{
   304  				Nodes: []*etcd.Node{},
   305  			},
   306  		},
   307  		E: nil,
   308  	}
   309  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   310  	tasks, err := registry.ListTasks(nil)
   311  	expectNoError(t, err)
   312  	if len(tasks) != 0 {
   313  		t.Errorf("Unexpected task list: %#v", tasks)
   314  	}
   315  }
   316  
   317  func TestEtcdListTasksNotFound(t *testing.T) {
   318  	fakeClient := MakeFakeEtcdClient(t)
   319  	key := "/registry/hosts/machine/tasks"
   320  	fakeClient.Data[key] = EtcdResponseWithError{
   321  		R: &etcd.Response{},
   322  		E: &etcd.EtcdError{ErrorCode: 100},
   323  	}
   324  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   325  	tasks, err := registry.ListTasks(nil)
   326  	expectNoError(t, err)
   327  	if len(tasks) != 0 {
   328  		t.Errorf("Unexpected task list: %#v", tasks)
   329  	}
   330  }
   331  
   332  func TestEtcdListTasks(t *testing.T) {
   333  	fakeClient := MakeFakeEtcdClient(t)
   334  	key := "/registry/hosts/machine/tasks"
   335  	fakeClient.Data[key] = EtcdResponseWithError{
   336  		R: &etcd.Response{
   337  			Node: &etcd.Node{
   338  				Nodes: []*etcd.Node{
   339  					&etcd.Node{
   340  						Value: util.MakeJSONString(Task{JSONBase: JSONBase{ID: "foo"}}),
   341  					},
   342  					&etcd.Node{
   343  						Value: util.MakeJSONString(Task{JSONBase: JSONBase{ID: "bar"}}),
   344  					},
   345  				},
   346  			},
   347  		},
   348  		E: nil,
   349  	}
   350  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   351  	tasks, err := registry.ListTasks(nil)
   352  	expectNoError(t, err)
   353  	if len(tasks) != 2 || tasks[0].ID != "foo" || tasks[1].ID != "bar" {
   354  		t.Errorf("Unexpected task list: %#v", tasks)
   355  	}
   356  }
   357  
   358  func TestEtcdListControllersNotFound(t *testing.T) {
   359  	fakeClient := MakeFakeEtcdClient(t)
   360  	key := "/registry/controllers"
   361  	fakeClient.Data[key] = EtcdResponseWithError{
   362  		R: &etcd.Response{},
   363  		E: &etcd.EtcdError{ErrorCode: 100},
   364  	}
   365  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   366  	controllers, err := registry.ListControllers()
   367  	expectNoError(t, err)
   368  	if len(controllers) != 0 {
   369  		t.Errorf("Unexpected controller list: %#v", controllers)
   370  	}
   371  }
   372  
   373  func TestEtcdListServicesNotFound(t *testing.T) {
   374  	fakeClient := MakeFakeEtcdClient(t)
   375  	key := "/registry/services/specs"
   376  	fakeClient.Data[key] = EtcdResponseWithError{
   377  		R: &etcd.Response{},
   378  		E: &etcd.EtcdError{ErrorCode: 100},
   379  	}
   380  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   381  	services, err := registry.ListServices()
   382  	expectNoError(t, err)
   383  	if len(services.Items) != 0 {
   384  		t.Errorf("Unexpected controller list: %#v", services)
   385  	}
   386  }
   387  
   388  func TestEtcdListControllers(t *testing.T) {
   389  	fakeClient := MakeFakeEtcdClient(t)
   390  	key := "/registry/controllers"
   391  	fakeClient.Data[key] = EtcdResponseWithError{
   392  		R: &etcd.Response{
   393  			Node: &etcd.Node{
   394  				Nodes: []*etcd.Node{
   395  					&etcd.Node{
   396  						Value: util.MakeJSONString(ReplicationController{JSONBase: JSONBase{ID: "foo"}}),
   397  					},
   398  					&etcd.Node{
   399  						Value: util.MakeJSONString(ReplicationController{JSONBase: JSONBase{ID: "bar"}}),
   400  					},
   401  				},
   402  			},
   403  		},
   404  		E: nil,
   405  	}
   406  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   407  	controllers, err := registry.ListControllers()
   408  	expectNoError(t, err)
   409  	if len(controllers) != 2 || controllers[0].ID != "foo" || controllers[1].ID != "bar" {
   410  		t.Errorf("Unexpected controller list: %#v", controllers)
   411  	}
   412  }
   413  
   414  func TestEtcdGetController(t *testing.T) {
   415  	fakeClient := MakeFakeEtcdClient(t)
   416  	fakeClient.Set("/registry/controllers/foo", util.MakeJSONString(ReplicationController{JSONBase: JSONBase{ID: "foo"}}), 0)
   417  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   418  	ctrl, err := registry.GetController("foo")
   419  	expectNoError(t, err)
   420  	if ctrl.ID != "foo" {
   421  		t.Errorf("Unexpected controller: %#v", ctrl)
   422  	}
   423  }
   424  
   425  func TestEtcdGetControllerNotFound(t *testing.T) {
   426  	fakeClient := MakeFakeEtcdClient(t)
   427  	fakeClient.Data["/registry/controllers/foo"] = EtcdResponseWithError{
   428  		R: &etcd.Response{
   429  			Node: nil,
   430  		},
   431  		E: &etcd.EtcdError{
   432  			ErrorCode: 100,
   433  		},
   434  	}
   435  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   436  	ctrl, err := registry.GetController("foo")
   437  	if ctrl != nil {
   438  		t.Errorf("Unexpected non-nil controller: %#v", ctrl)
   439  	}
   440  	if err == nil {
   441  		t.Error("Unexpected non-error.")
   442  	}
   443  }
   444  
   445  func TestEtcdDeleteController(t *testing.T) {
   446  	fakeClient := MakeFakeEtcdClient(t)
   447  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   448  	err := registry.DeleteController("foo")
   449  	expectNoError(t, err)
   450  	if len(fakeClient.deletedKeys) != 1 {
   451  		t.Errorf("Expected 1 delete, found %#v", fakeClient.deletedKeys)
   452  	}
   453  	key := "/registry/controllers/foo"
   454  	if fakeClient.deletedKeys[0] != key {
   455  		t.Errorf("Unexpected key: %s, expected %s", fakeClient.deletedKeys[0], key)
   456  	}
   457  }
   458  
   459  func TestEtcdCreateController(t *testing.T) {
   460  	fakeClient := MakeFakeEtcdClient(t)
   461  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   462  	err := registry.CreateController(ReplicationController{
   463  		JSONBase: JSONBase{
   464  			ID: "foo",
   465  		},
   466  	})
   467  	expectNoError(t, err)
   468  	resp, err := fakeClient.Get("/registry/controllers/foo", false, false)
   469  	expectNoError(t, err)
   470  	var ctrl ReplicationController
   471  	err = json.Unmarshal([]byte(resp.Node.Value), &ctrl)
   472  	expectNoError(t, err)
   473  	if ctrl.ID != "foo" {
   474  		t.Errorf("Unexpected task: %#v %s", ctrl, resp.Node.Value)
   475  	}
   476  }
   477  
   478  func TestEtcdUpdateController(t *testing.T) {
   479  	fakeClient := MakeFakeEtcdClient(t)
   480  	fakeClient.Set("/registry/controllers/foo", util.MakeJSONString(ReplicationController{JSONBase: JSONBase{ID: "foo"}}), 0)
   481  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   482  	err := registry.UpdateController(ReplicationController{
   483  		JSONBase: JSONBase{ID: "foo"},
   484  		DesiredState: ReplicationControllerState{
   485  			Replicas: 2,
   486  		},
   487  	})
   488  	expectNoError(t, err)
   489  	ctrl, err := registry.GetController("foo")
   490  	if ctrl.DesiredState.Replicas != 2 {
   491  		t.Errorf("Unexpected controller: %#v", ctrl)
   492  	}
   493  }
   494  
   495  func TestEtcdListServices(t *testing.T) {
   496  	fakeClient := MakeFakeEtcdClient(t)
   497  	key := "/registry/services/specs"
   498  	fakeClient.Data[key] = EtcdResponseWithError{
   499  		R: &etcd.Response{
   500  			Node: &etcd.Node{
   501  				Nodes: []*etcd.Node{
   502  					&etcd.Node{
   503  						Value: util.MakeJSONString(Service{JSONBase: JSONBase{ID: "foo"}}),
   504  					},
   505  					&etcd.Node{
   506  						Value: util.MakeJSONString(Service{JSONBase: JSONBase{ID: "bar"}}),
   507  					},
   508  				},
   509  			},
   510  		},
   511  		E: nil,
   512  	}
   513  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   514  	services, err := registry.ListServices()
   515  	expectNoError(t, err)
   516  	if len(services.Items) != 2 || services.Items[0].ID != "foo" || services.Items[1].ID != "bar" {
   517  		t.Errorf("Unexpected task list: %#v", services)
   518  	}
   519  }
   520  
   521  func TestEtcdCreateService(t *testing.T) {
   522  	fakeClient := MakeFakeEtcdClient(t)
   523  	fakeClient.Data["/registry/services/specs/foo"] = EtcdResponseWithError{
   524  		R: &etcd.Response{
   525  			Node: nil,
   526  		},
   527  		E: &etcd.EtcdError{ErrorCode: 100},
   528  	}
   529  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   530  	err := registry.CreateService(Service{
   531  		JSONBase: JSONBase{ID: "foo"},
   532  	})
   533  	expectNoError(t, err)
   534  	resp, err := fakeClient.Get("/registry/services/specs/foo", false, false)
   535  	expectNoError(t, err)
   536  	var service Service
   537  	err = json.Unmarshal([]byte(resp.Node.Value), &service)
   538  	expectNoError(t, err)
   539  	if service.ID != "foo" {
   540  		t.Errorf("Unexpected service: %#v %s", service, resp.Node.Value)
   541  	}
   542  }
   543  
   544  func TestEtcdGetService(t *testing.T) {
   545  	fakeClient := MakeFakeEtcdClient(t)
   546  	fakeClient.Set("/registry/services/specs/foo", util.MakeJSONString(Service{JSONBase: JSONBase{ID: "foo"}}), 0)
   547  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   548  	service, err := registry.GetService("foo")
   549  	expectNoError(t, err)
   550  	if service.ID != "foo" {
   551  		t.Errorf("Unexpected task: %#v", service)
   552  	}
   553  }
   554  
   555  func TestEtcdGetServiceNotFound(t *testing.T) {
   556  	fakeClient := MakeFakeEtcdClient(t)
   557  	fakeClient.Data["/registry/services/specs/foo"] = EtcdResponseWithError{
   558  		R: &etcd.Response{
   559  			Node: nil,
   560  		},
   561  		E: &etcd.EtcdError{
   562  			ErrorCode: 100,
   563  		},
   564  	}
   565  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   566  	_, err := registry.GetService("foo")
   567  	if err == nil {
   568  		t.Errorf("Unexpected non-error.")
   569  	}
   570  }
   571  
   572  func TestEtcdDeleteService(t *testing.T) {
   573  	fakeClient := MakeFakeEtcdClient(t)
   574  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   575  	err := registry.DeleteService("foo")
   576  	expectNoError(t, err)
   577  	if len(fakeClient.deletedKeys) != 2 {
   578  		t.Errorf("Expected 2 delete, found %#v", fakeClient.deletedKeys)
   579  	}
   580  	key := "/registry/services/specs/foo"
   581  	if fakeClient.deletedKeys[0] != key {
   582  		t.Errorf("Unexpected key: %s, expected %s", fakeClient.deletedKeys[0], key)
   583  	}
   584  	key = "/registry/services/endpoints/foo"
   585  	if fakeClient.deletedKeys[1] != key {
   586  		t.Errorf("Unexpected key: %s, expected %s", fakeClient.deletedKeys[1], key)
   587  	}
   588  }
   589  
   590  func TestEtcdUpdateService(t *testing.T) {
   591  	fakeClient := MakeFakeEtcdClient(t)
   592  	fakeClient.Set("/registry/services/specs/foo", util.MakeJSONString(Service{JSONBase: JSONBase{ID: "foo"}}), 0)
   593  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   594  	err := registry.UpdateService(Service{
   595  		JSONBase: JSONBase{ID: "foo"},
   596  		Labels: map[string]string{
   597  			"baz": "bar",
   598  		},
   599  	})
   600  	expectNoError(t, err)
   601  	svc, err := registry.GetService("foo")
   602  	if svc.Labels["baz"] != "bar" {
   603  		t.Errorf("Unexpected service: %#v", svc)
   604  	}
   605  }
   606  
   607  func TestEtcdUpdateEndpoints(t *testing.T) {
   608  	fakeClient := MakeFakeEtcdClient(t)
   609  	registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"})
   610  	endpoints := Endpoints{
   611  		Name:      "foo",
   612  		Endpoints: []string{"baz", "bar"},
   613  	}
   614  	err := registry.UpdateEndpoints(endpoints)
   615  	expectNoError(t, err)
   616  	response, err := fakeClient.Get("/registry/services/endpoints/foo", false, false)
   617  	expectNoError(t, err)
   618  	var endpointsOut Endpoints
   619  	err = json.Unmarshal([]byte(response.Node.Value), &endpointsOut)
   620  	if !reflect.DeepEqual(endpoints, endpointsOut) {
   621  		t.Errorf("Unexpected endpoints: %#v, expected %#v", endpointsOut, endpoints)
   622  	}
   623  }