func TestServiceRegistryIPReloadFromStorage(t *testing.T) { registry := registrytest.NewServiceRegistry() machines := []string{"foo", "bar", "baz"} nodeRegistry := registrytest.NewMinionRegistry(machines, api.NodeResources{}) endpoints := ®istrytest.EndpointRegistry{} rest1 := NewStorage(registry, nodeRegistry, endpoints, makeIPNet(t), "kubernetes") rest1.portalMgr.randomAttempts = 0 svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.AffinityTypeNone, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, }}, }, } ctx := api.NewDefaultContext() rest1.Create(ctx, svc) svc = &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.AffinityTypeNone, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, }}, }, } rest1.Create(ctx, svc) // This will reload from storage, finding the previous 2 nodeRegistry = registrytest.NewMinionRegistry(machines, api.NodeResources{}) rest2 := NewStorage(registry, nodeRegistry, endpoints, makeIPNet(t), "kubernetes") rest2.portalMgr.randomAttempts = 0 svc = &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.AffinityTypeNone, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, }}, }, } created_svc, _ := rest2.Create(ctx, svc) created_service := created_svc.(*api.Service) if created_service.Spec.PortalIP != "1.2.3.3" { t.Errorf("Unexpected PortalIP: %s", created_service.Spec.PortalIP) } }
func TestGetServersToValidate(t *testing.T) { master := Master{} config := Config{} fakeClient := tools.NewFakeEtcdClient(t) fakeClient.Machines = []string{"http://machine1:4001", "http://machine2", "http://machine3:4003"} config.EtcdHelper = tools.NewEtcdHelper(fakeClient, latest.Codec, etcdtest.PathPrefix()) config.EtcdHelper.Versioner = nil master.nodeRegistry = registrytest.NewMinionRegistry([]string{"node1", "node2"}, api.NodeResources{}) servers := master.getServersToValidate(&config, true) if len(servers) != 7 { t.Errorf("unexpected server list: %#v", servers) } for _, server := range []string{"scheduler", "controller-manager", "etcd-0", "etcd-1", "etcd-2", "node-0", "node-1"} { if _, ok := servers[server]; !ok { t.Errorf("server list missing: %s", server) } } servers = master.getServersToValidate(&config, false) if len(servers) != 5 { t.Errorf("unexpected server list: %#v", servers) } for _, server := range []string{"scheduler", "controller-manager", "etcd-0", "etcd-1", "etcd-2"} { if _, ok := servers[server]; !ok { t.Errorf("server list missing: %s", server) } } }
func TestMinionStorageValidatesCreate(t *testing.T) { storage := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) ctx := api.NewContext() validSelector := map[string]string{"a": "b"} invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} failureCases := map[string]api.Minion{ "zero-length Name": { ObjectMeta: api.ObjectMeta{ Name: "", Labels: validSelector, }, Status: api.NodeStatus{ HostIP: "something", }, }, "invalid-labels": { ObjectMeta: api.ObjectMeta{ Name: "abc-123", Labels: invalidSelector, }, }, } for _, failureCase := range failureCases { c, err := storage.Create(ctx, &failureCase) if c != nil { t.Errorf("Expected nil channel") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
func TestBasicDelegation(t *testing.T) { mockMinionRegistry := registrytest.NewMinionRegistry([]string{"m1", "m2", "m3"}) healthy := HealthyRegistry{ delegate: mockMinionRegistry, client: alwaysYes{}, } list, err := healthy.List() if err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(list, mockMinionRegistry.Minions) { t.Errorf("Expected %v, Got %v", mockMinionRegistry.Minions, list) } err = healthy.Insert("foo") if err != nil { t.Errorf("unexpected error: %v", err) } ok, err := healthy.Contains("m1") if err != nil { t.Errorf("unexpected error: %v", err) } if !ok { t.Errorf("Unexpected absence of 'm1'") } ok, err = healthy.Contains("m5") if err != nil { t.Errorf("unexpected error: %v", err) } if ok { t.Errorf("Unexpected presence of 'm5'") } }
func TestServiceRegistryExternalService(t *testing.T) { ctx := api.NewDefaultContext() registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Port: 6502, Selector: map[string]string{"bar": "baz"}, CreateExternalLoadBalancer: true, }, } c, _ := storage.Create(ctx, svc) <-c if len(fakeCloud.Calls) != 2 || fakeCloud.Calls[0] != "get-zone" || fakeCloud.Calls[1] != "create" { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } srv, err := registry.GetService(ctx, svc.Name) if err != nil { t.Errorf("Unexpected error: %v", err) } if srv == nil { t.Errorf("Failed to find service: %s", svc.Name) } }
func TestMinionRegistryValidatesCreate(t *testing.T) { storage := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) ctx := api.NewContext() failureCases := map[string]api.Node{ "zero-length Name": { ObjectMeta: api.ObjectMeta{ Name: "", Labels: validSelector, }, Status: api.NodeStatus{ Addresses: []api.NodeAddress{ {Type: api.NodeLegacyHostIP, Address: "something"}, }, }, }, "invalid-labels": { ObjectMeta: api.ObjectMeta{ Name: "abc-123", Labels: invalidSelector, }, }, } for _, failureCase := range failureCases { c, err := storage.Create(ctx, &failureCase) if c != nil { t.Errorf("Expected nil object") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
func TestBasicDelegation(t *testing.T) { ctx := api.NewContext() mockMinionRegistry := registrytest.NewMinionRegistry([]string{"m1", "m2", "m3"}, api.NodeResources{}) healthy := HealthyRegistry{ delegate: mockMinionRegistry, client: alwaysYes{}, } list, err := healthy.ListMinions(ctx) if err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(list, &mockMinionRegistry.Minions) { t.Errorf("Expected %v, Got %v", mockMinionRegistry.Minions, list) } err = healthy.CreateMinion(ctx, &api.Minion{ ObjectMeta: api.ObjectMeta{Name: "foo"}, }) if err != nil { t.Errorf("unexpected error: %v", err) } minion, err := healthy.GetMinion(ctx, "m1") if err != nil { t.Errorf("unexpected error: %v", err) } if minion == nil { t.Errorf("Unexpected absence of 'm1'") } minion, err = healthy.GetMinion(ctx, "m5") if err == nil { t.Errorf("unexpected non-error") } if minion != nil { t.Errorf("Unexpected presence of 'm5'") } }
func TestServiceRegistryExternalServiceError(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{ Err: fmt.Errorf("test error"), } machines := []string{"foo", "bar", "baz"} storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Port: 6502, Selector: map[string]string{"bar": "baz"}, CreateExternalLoadBalancer: true, }, } ctx := api.NewDefaultContext() c, _ := storage.Create(ctx, svc) <-c if len(fakeCloud.Calls) != 1 || fakeCloud.Calls[0] != "get-zone" { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } if registry.Service != nil { t.Errorf("Expected registry.CreateService to not get called, but it got %#v", registry.Service) } }
func TestCachingInsert(t *testing.T) { fakeClock := fakeClock{ now: time.Unix(0, 0), } fakeRegistry := registrytest.NewMinionRegistry([]string{"m1", "m2"}) expected := []string{"m1", "m2", "m3"} cache := CachingRegistry{ delegate: fakeRegistry, ttl: 1 * time.Second, clock: &fakeClock, lastUpdate: fakeClock.Now().Unix(), minions: expected, } err := cache.Insert("foo") if err != nil { t.Errorf("unexpected error: %v", err) } list, err := cache.List() if err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(list, fakeRegistry.Minions) { t.Errorf("expected: %v, got %v", fakeRegistry.Minions, list) } }
func TestServiceRegistryResourceLocation(t *testing.T) { ctx := api.NewDefaultContext() registry := registrytest.NewServiceRegistry() registry.Endpoints = api.Endpoints{Endpoints: []string{"foo:80"}} fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) registry.CreateService(ctx, &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, }, }) redirector := apiserver.Redirector(storage) location, err := redirector.ResourceLocation(ctx, "foo") if err != nil { t.Errorf("Unexpected error: %v", err) } if e, a := "foo:80", location; e != a { t.Errorf("Expected %v, but got %v", e, a) } if e, a := "foo", registry.GottenID; e != a { t.Errorf("Expected %v, but got %v", e, a) } // Test error path registry.Err = fmt.Errorf("fake error") if _, err = redirector.ResourceLocation(ctx, "foo"); err == nil { t.Errorf("unexpected nil error") } }
func TestServiceRegistryIPExternalLoadBalancer(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, CreateExternalLoadBalancer: true, }, } ctx := api.NewDefaultContext() c, _ := rest.Create(ctx, svc) created_svc := <-c created_service := created_svc.Object.(*api.Service) if created_service.Spec.Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Port) } if created_service.Spec.PortalIP != "1.2.3.1" { t.Errorf("Unexpected PortalIP: %s", created_service.Spec.PortalIP) } if created_service.Spec.ProxyPort != 6502 { t.Errorf("Unexpected ProxyPort: %d", created_service.Spec.ProxyPort) } }
func TestFiltering(t *testing.T) { ctx := api.NewContext() mockMinionRegistry := registrytest.NewMinionRegistry([]string{"m1", "m2", "m3"}, api.NodeResources{}) healthy := NewHealthyRegistry( mockMinionRegistry, ¬Minion{minion: "m1"}, &util.FakeClock{}, 60*time.Second, ) expected := []string{"m1", "m2", "m3"} list, err := healthy.ListMinions(ctx) if err != nil { t.Errorf("unexpected error: %v", err) } expectedMinions := registrytest.MakeMinionList(expected, api.NodeResources{}) expectedMinions.Items[0].Status.Conditions = []api.NodeCondition{{Kind: api.NodeReady, Status: api.ConditionNone}} expectedMinions.Items[1].Status.Conditions = []api.NodeCondition{{Kind: api.NodeReady, Status: api.ConditionFull}} expectedMinions.Items[2].Status.Conditions = []api.NodeCondition{{Kind: api.NodeReady, Status: api.ConditionFull}} if !reflect.DeepEqual(list, expectedMinions) { t.Errorf("Expected %v, Got %v", expected, list) } minion, err := healthy.GetMinion(ctx, "m1") if err != nil { t.Errorf("unexpected error: %v", err) } if minion == nil { t.Errorf("Unexpected empty 'm1'") } }
func TestMinionRegistryREST(t *testing.T) { ms := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) ctx := api.NewContext() if obj, err := ms.Get(ctx, "foo"); err != nil || obj.(*api.Node).Name != "foo" { t.Errorf("missing expected object") } if obj, err := ms.Get(ctx, "bar"); err != nil || obj.(*api.Node).Name != "bar" { t.Errorf("missing expected object") } if _, err := ms.Get(ctx, "baz"); !errors.IsNotFound(err) { t.Errorf("has unexpected error: %v", err) } obj, err := ms.Create(ctx, &api.Node{ObjectMeta: api.ObjectMeta{Name: "baz"}}) if err != nil { t.Fatalf("insert failed: %v", err) } if !api.HasObjectMetaSystemFieldValues(&obj.(*api.Node).ObjectMeta) { t.Errorf("storage did not populate object meta field values") } if m, ok := obj.(*api.Node); !ok || m.Name != "baz" { t.Errorf("insert return value was weird: %#v", obj) } if obj, err := ms.Get(ctx, "baz"); err != nil || obj.(*api.Node).Name != "baz" { t.Errorf("insert didn't actually insert") } obj, err = ms.Delete(ctx, "bar") if err != nil { t.Fatalf("delete failed") } if s, ok := obj.(*api.Status); !ok || s.Status != api.StatusSuccess { t.Errorf("delete return value was weird: %#v", obj) } if _, err := ms.Get(ctx, "bar"); !errors.IsNotFound(err) { t.Errorf("delete didn't actually delete: %v", err) } _, err = ms.Delete(ctx, "bar") if err != ErrDoesNotExist { t.Fatalf("delete returned wrong error") } list, err := ms.List(ctx, labels.Everything(), fields.Everything()) if err != nil { t.Errorf("got error calling List") } expect := []api.Node{ { ObjectMeta: api.ObjectMeta{Name: "foo"}, }, { ObjectMeta: api.ObjectMeta{Name: "baz"}, }, } nodeList := list.(*api.NodeList) if len(expect) != len(nodeList.Items) || !contains(nodeList, "foo") || !contains(nodeList, "baz") { t.Errorf("Unexpected list value: %#v", list) } }
func TestMinionREST(t *testing.T) { ms := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) ctx := api.NewContext() if obj, err := ms.Get(ctx, "foo"); err != nil || obj.(*api.Minion).Name != "foo" { t.Errorf("missing expected object") } if obj, err := ms.Get(ctx, "bar"); err != nil || obj.(*api.Minion).Name != "bar" { t.Errorf("missing expected object") } if _, err := ms.Get(ctx, "baz"); err != ErrDoesNotExist { t.Errorf("has unexpected object") } c, err := ms.Create(ctx, &api.Minion{ObjectMeta: api.ObjectMeta{Name: "baz"}}) if err != nil { t.Errorf("insert failed") } obj := <-c if m, ok := obj.Object.(*api.Minion); !ok || m.Name != "baz" { t.Errorf("insert return value was weird: %#v", obj) } if obj, err := ms.Get(ctx, "baz"); err != nil || obj.(*api.Minion).Name != "baz" { t.Errorf("insert didn't actually insert") } c, err = ms.Delete(ctx, "bar") if err != nil { t.Errorf("delete failed") } obj = <-c if s, ok := obj.Object.(*api.Status); !ok || s.Status != api.StatusSuccess { t.Errorf("delete return value was weird: %#v", obj) } if _, err := ms.Get(ctx, "bar"); err != ErrDoesNotExist { t.Errorf("delete didn't actually delete") } _, err = ms.Delete(ctx, "bar") if err != ErrDoesNotExist { t.Errorf("delete returned wrong error") } list, err := ms.List(ctx, labels.Everything(), labels.Everything()) if err != nil { t.Errorf("got error calling List") } expect := []api.Minion{ { ObjectMeta: api.ObjectMeta{Name: "foo"}, }, { ObjectMeta: api.ObjectMeta{Name: "baz"}, }, } nodeList := list.(*api.MinionList) if len(expect) != len(nodeList.Items) || !contains(nodeList, "foo") || !contains(nodeList, "baz") { t.Errorf("Unexpected list value: %#v", list) } }
func TestServiceRegistryIPAllocation(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) rest.portalMgr.randomAttempts = 0 svc1 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, }, } ctx := api.NewDefaultContext() c1, _ := rest.Create(ctx, svc1) created_svc1 := <-c1 created_service_1 := created_svc1.Object.(*api.Service) if created_service_1.Name != "foo" { t.Errorf("Expected foo, but got %v", created_service_1.Name) } if created_service_1.Spec.PortalIP != "1.2.3.1" { t.Errorf("Unexpected PortalIP: %s", created_service_1.Spec.PortalIP) } svc2 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "bar"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, }} ctx = api.NewDefaultContext() c2, _ := rest.Create(ctx, svc2) created_svc2 := <-c2 created_service_2 := created_svc2.Object.(*api.Service) if created_service_2.Name != "bar" { t.Errorf("Expected bar, but got %v", created_service_2.Name) } if created_service_2.Spec.PortalIP != "1.2.3.2" { // new IP t.Errorf("Unexpected PortalIP: %s", created_service_2.Spec.PortalIP) } svc3 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "quux"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, PortalIP: "1.2.3.93", Port: 6502, }, } ctx = api.NewDefaultContext() c3, _ := rest.Create(ctx, svc3) created_svc3 := <-c3 created_service_3 := created_svc3.Object.(*api.Service) if created_service_3.Spec.PortalIP != "1.2.3.93" { // specific IP t.Errorf("Unexpected PortalIP: %s", created_service_3.Spec.PortalIP) } }
func TestServiceRegistryIPReloadFromStorage(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} rest1 := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) rest1.portalMgr.randomAttempts = 0 svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, }, } ctx := api.NewDefaultContext() c, _ := rest1.Create(ctx, svc) <-c svc = &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, }, } c, _ = rest1.Create(ctx, svc) <-c // This will reload from storage, finding the previous 2 rest2 := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) rest2.portalMgr.randomAttempts = 0 svc = &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, }, } c, _ = rest2.Create(ctx, svc) created_svc := <-c created_service := created_svc.Object.(*api.Service) if created_service.Spec.PortalIP != "1.2.3.3" { t.Errorf("Unexpected PortalIP: %s", created_service.Spec.PortalIP) } }
func NewTestREST(t *testing.T, endpoints *api.EndpointsList) (*REST, *registrytest.ServiceRegistry) { registry := registrytest.NewServiceRegistry() machines := []string{"foo", "bar", "baz"} endpointRegistry := ®istrytest.EndpointRegistry{ Endpoints: endpoints, } nodeRegistry := registrytest.NewMinionRegistry(machines, api.NodeResources{}) storage := NewStorage(registry, nodeRegistry, endpointRegistry, makeIPNet(t), "kubernetes") return storage, registry }
func TestServiceRegistryIPUpdate(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) rest.portalMgr.randomAttempts = 0 svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, }, } ctx := api.NewDefaultContext() c, _ := rest.Create(ctx, svc) created_svc := <-c created_service := created_svc.Object.(*api.Service) if created_service.Spec.Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Port) } if created_service.Spec.PortalIP != "1.2.3.1" { t.Errorf("Unexpected PortalIP: %s", created_service.Spec.PortalIP) } if created_service.Spec.ProxyPort != 0 { t.Errorf("Unexpected ProxyPort: %d", created_service.Spec.ProxyPort) } update := new(api.Service) *update = *created_service update.Spec.Port = 6503 update.Spec.ProxyPort = 309 // should be ignored c, _ = rest.Update(ctx, update) updated_svc := <-c updated_service := updated_svc.Object.(*api.Service) if updated_service.Spec.Port != 6503 { t.Errorf("Expected port 6503, but got %v", updated_service.Spec.Port) } if updated_service.Spec.ProxyPort != 0 { // unchanged, despite trying t.Errorf("Unexpected ProxyPort: %d", updated_service.Spec.ProxyPort) } *update = *created_service update.Spec.Port = 6503 update.Spec.PortalIP = "1.2.3.76" // error c, _ = rest.Update(ctx, update) result := <-c st := result.Object.(*api.Status) if st.Reason != api.StatusReasonInvalid { t.Errorf("Expected to get an invalid error, got %v", st) } }
func TestMinionStorageInvalidUpdate(t *testing.T) { storage := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) ctx := api.NewContext() obj, err := storage.Get(ctx, "foo") if err != nil { t.Errorf("Unexpected error: %v", err) } minion, ok := obj.(*api.Minion) if !ok { t.Fatalf("Object is not a minion: %#v", obj) } minion.Status.HostIP = "1.2.3.4" if _, err = storage.Update(ctx, minion); err == nil { t.Error("Unexpected non-error.") } }
func NewTestREST(t *testing.T, endpoints *api.EndpointsList) (*REST, *registrytest.ServiceRegistry) { registry := registrytest.NewServiceRegistry() machines := []string{"foo", "bar", "baz"} endpointRegistry := ®istrytest.EndpointRegistry{ Endpoints: endpoints, } nodeRegistry := registrytest.NewMinionRegistry(machines, api.NodeResources{}) r := ipallocator.NewCIDRRange(makeIPNet(t)) portRange := util.PortRange{Base: 30000, Size: 1000} portAllocator := portallocator.NewPortAllocator(portRange) storage := NewStorage(registry, nodeRegistry, endpointRegistry, r, portAllocator, "kubernetes") return storage, registry }
func TestServiceRegistryIPReallocation(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest.portalMgr.randomAttempts = 0 svc1 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, Protocol: api.ProtocolTCP, SessionAffinity: api.AffinityTypeNone, }, } ctx := api.NewDefaultContext() created_svc1, _ := rest.Create(ctx, svc1) created_service_1 := created_svc1.(*api.Service) if created_service_1.Name != "foo" { t.Errorf("Expected foo, but got %v", created_service_1.Name) } if created_service_1.Spec.PortalIP != "1.2.3.1" { t.Errorf("Unexpected PortalIP: %s", created_service_1.Spec.PortalIP) } rest.Delete(ctx, created_service_1.Name) svc2 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "bar"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, Protocol: api.ProtocolTCP, SessionAffinity: api.AffinityTypeNone, }, } ctx = api.NewDefaultContext() created_svc2, _ := rest.Create(ctx, svc2) created_service_2 := created_svc2.(*api.Service) if created_service_2.Name != "bar" { t.Errorf("Expected bar, but got %v", created_service_2.Name) } if created_service_2.Spec.PortalIP != "1.2.3.1" { // same IP as before t.Errorf("Unexpected PortalIP: %s", created_service_2.Spec.PortalIP) } }
func TestServiceRegistryIPUpdate(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest.portalMgr.randomAttempts = 0 svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, Protocol: api.ProtocolTCP, SessionAffinity: api.AffinityTypeNone, }, } ctx := api.NewDefaultContext() created_svc, _ := rest.Create(ctx, svc) created_service := created_svc.(*api.Service) if created_service.Spec.Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Port) } if created_service.Spec.PortalIP != "1.2.3.1" { t.Errorf("Unexpected PortalIP: %s", created_service.Spec.PortalIP) } update := new(api.Service) *update = *created_service update.Spec.Port = 6503 updated_svc, _, _ := rest.Update(ctx, update) updated_service := updated_svc.(*api.Service) if updated_service.Spec.Port != 6503 { t.Errorf("Expected port 6503, but got %v", updated_service.Spec.Port) } *update = *created_service update.Spec.Port = 6503 update.Spec.PortalIP = "1.2.3.76" // error _, _, err := rest.Update(ctx, update) if err == nil || !errors.IsInvalid(err) { t.Error("Unexpected error type: %v", err) } }
func TestServiceRegistryIPReallocation(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) svc1 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, }, } ctx := api.NewDefaultContext() c1, _ := rest.Create(ctx, svc1) created_svc1 := <-c1 created_service_1 := created_svc1.Object.(*api.Service) if created_service_1.Name != "foo" { t.Errorf("Expected foo, but got %v", created_service_1.Name) } if created_service_1.Spec.PortalIP != "1.2.3.1" { t.Errorf("Unexpected PortalIP: %s", created_service_1.Spec.PortalIP) } c, _ := rest.Delete(ctx, created_service_1.Name) <-c svc2 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "bar"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, }, } ctx = api.NewDefaultContext() c2, _ := rest.Create(ctx, svc2) created_svc2 := <-c2 created_service_2 := created_svc2.Object.(*api.Service) if created_service_2.Name != "bar" { t.Errorf("Expected bar, but got %v", created_service_2.Name) } if created_service_2.Spec.PortalIP != "1.2.3.1" { // same IP as before t.Errorf("Unexpected PortalIP: %s", created_service_2.Spec.PortalIP) } }
func TestServiceRegistryCreate(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) storage.portalMgr.randomAttempts = 0 svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Port: 6502, Selector: map[string]string{"bar": "baz"}, }, } ctx := api.NewDefaultContext() c, _ := storage.Create(ctx, svc) created_svc := <-c created_service := created_svc.Object.(*api.Service) if !api.HasObjectMetaSystemFieldValues(&created_service.ObjectMeta) { t.Errorf("storage did not populate object meta field values") } if created_service.Name != "foo" { t.Errorf("Expected foo, but got %v", created_service.Name) } if created_service.CreationTimestamp.IsZero() { t.Errorf("Expected timestamp to be set, got: %v", created_service.CreationTimestamp) } if created_service.Spec.PortalIP != "1.2.3.1" { t.Errorf("Unexpected PortalIP: %s", created_service.Spec.PortalIP) } if created_service.Spec.ProxyPort != 0 { t.Errorf("Unexpected ProxyPort: %d", created_service.Spec.ProxyPort) } if len(fakeCloud.Calls) != 0 { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } srv, err := registry.GetService(ctx, svc.Name) if err != nil { t.Errorf("unexpected error: %v", err) } if srv == nil { t.Errorf("Failed to find service: %s", svc.Name) } }
func TestServiceRegistryUpdateExternalService(t *testing.T) { ctx := api.NewDefaultContext() registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") // Create non-external load balancer. svc1 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Port: 6502, Selector: map[string]string{"bar": "baz"}, CreateExternalLoadBalancer: false, Protocol: api.ProtocolTCP, SessionAffinity: api.AffinityTypeNone, }, } storage.Create(ctx, svc1) if len(fakeCloud.Calls) != 0 { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } // Modify load balancer to be external. svc2 := new(api.Service) *svc2 = *svc1 svc2.Spec.CreateExternalLoadBalancer = true storage.Update(ctx, svc2) if len(fakeCloud.Calls) != 2 || fakeCloud.Calls[0] != "get-zone" || fakeCloud.Calls[1] != "create" { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } // Change port. svc3 := new(api.Service) *svc3 = *svc2 svc3.Spec.Port = 6504 storage.Update(ctx, svc3) if len(fakeCloud.Calls) != 6 || fakeCloud.Calls[0] != "get-zone" || fakeCloud.Calls[1] != "create" || fakeCloud.Calls[2] != "get-zone" || fakeCloud.Calls[3] != "delete" || fakeCloud.Calls[4] != "get-zone" || fakeCloud.Calls[5] != "create" { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } }
func TestCreate(t *testing.T) { registry := registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{}) test := resttest.New(t, NewREST(registry), registry.SetError).ClusterScope() test.TestCreate( // valid &api.Node{ Status: api.NodeStatus{ Addresses: []api.NodeAddress{ {Type: api.NodeLegacyHostIP, Address: "something"}, }, }, }, // invalid &api.Node{ ObjectMeta: api.ObjectMeta{ Labels: invalidSelector, }, }) }
func TestMinionStorageValidUpdate(t *testing.T) { storage := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) ctx := api.NewContext() obj, err := storage.Get(ctx, "foo") if err != nil { t.Errorf("Unexpected error: %v", err) } minion, ok := obj.(*api.Minion) if !ok { t.Fatalf("Object is not a minion: %#v", obj) } minion.Labels = map[string]string{ "foo": "bar", "baz": "home", } if _, err = storage.Update(ctx, minion); err != nil { t.Errorf("Unexpected error: %v", err) } }
func TestServiceRegistryGet(t *testing.T) { ctx := api.NewDefaultContext() registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t)) registry.CreateService(ctx, &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, }, }) storage.Get(ctx, "foo") if len(fakeCloud.Calls) != 0 { t.Errorf("Unexpected call(s): %#v", fakeCloud.Calls) } if e, a := "foo", registry.GottenID; e != a { t.Errorf("Expected %v, but got %v", e, a) } }
func TestMinionRESTWithHealthCheck(t *testing.T) { minionRegistry := registrytest.NewMinionRegistry([]string{}, api.NodeResources{}) minionHealthRegistry := HealthyRegistry{ delegate: minionRegistry, client: ¬Minion{minion: "m1"}, } ms := NewREST(&minionHealthRegistry) ctx := api.NewContext() c, err := ms.Create(ctx, &api.Minion{ObjectMeta: api.ObjectMeta{Name: "m1"}}) if err != nil { t.Errorf("insert failed") } result := <-c if m, ok := result.Object.(*api.Minion); !ok || m.Name != "m1" { t.Errorf("insert return value was weird: %#v", result) } if _, err := ms.Get(ctx, "m1"); err == nil { t.Errorf("node is unhealthy, expect no result from apiserver") } }
func TestServiceRegistryIPExternalLoadBalancer(t *testing.T) { registry := registrytest.NewServiceRegistry() fakeCloud := &cloud.FakeCloud{} machines := []string{"foo", "bar", "baz"} rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest.portalMgr.randomAttempts = 0 svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Port: 6502, CreateExternalLoadBalancer: true, Protocol: api.ProtocolTCP, SessionAffinity: api.AffinityTypeNone, }, } ctx := api.NewDefaultContext() created_svc, _ := rest.Create(ctx, svc) created_service := created_svc.(*api.Service) if created_service.Spec.Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Port) } if created_service.Spec.PortalIP != "1.2.3.1" { t.Errorf("Unexpected PortalIP: %s", created_service.Spec.PortalIP) } update := new(api.Service) *update = *created_service _, _, err := rest.Update(ctx, update) if err != nil { t.Errorf("Unexpected error %v", err) } if len(fakeCloud.Balancers) != 1 || fakeCloud.Balancers[0].Name != "kubernetes-default-foo" || fakeCloud.Balancers[0].Port != 6502 { t.Errorf("Unexpected balancer created: %v", fakeCloud.Balancers) } }