// TestControllerServicePorts verifies master extraServicePorts are // correctly copied into controller func TestControllerServicePorts(t *testing.T) { master, _, assert := setUp(t) master.namespaceRegistry = namespace.NewRegistry(nil) master.serviceRegistry = registrytest.NewServiceRegistry() master.endpointRegistry = endpoint.NewRegistry(nil) master.extraServicePorts = []api.ServicePort{ { Name: "additional-port-1", Port: 1000, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(1000), }, { Name: "additional-port-2", Port: 1010, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(1010), }, } controller := master.NewBootstrapController() assert.Equal(1000, controller.ExtraServicePorts[0].Port) assert.Equal(1010, controller.ExtraServicePorts[1].Port) }
func TestServiceRegistryUpdateMultiPortExternalService(t *testing.T) { ctx := api.NewDefaultContext() storage, _ := NewTestREST(t, nil) // Create external load balancer. svc1 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeLoadBalancer, Ports: []api.ServicePort{{ Name: "p", Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }, { Name: "q", Port: 8086, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(8086), }}, }, } if _, err := storage.Create(ctx, svc1); err != nil { t.Fatalf("Unexpected error: %v", err) } // Modify ports svc2 := deepCloneService(svc1) svc2.Spec.Ports[1].Port = 8088 if _, _, err := storage.Update(ctx, svc2); err != nil { t.Fatalf("Unexpected error: %v", err) } }
func addDefaultingFuncs() { api.Scheme.AddDefaultingFuncs( func(obj *APIVersion) { if len(obj.APIGroup) == 0 { obj.APIGroup = "experimental" } }, func(obj *DaemonSet) { var labels map[string]string if obj.Spec.Template != nil { labels = obj.Spec.Template.Labels } // TODO: support templates defined elsewhere when we support them in the API if labels != nil { if len(obj.Spec.Selector) == 0 { obj.Spec.Selector = labels } if len(obj.Labels) == 0 { obj.Labels = labels } } }, func(obj *Deployment) { // Set DeploymentSpec.Replicas to 1 if it is not set. if obj.Spec.Replicas == nil { obj.Spec.Replicas = new(int) *obj.Spec.Replicas = 1 } strategy := &obj.Spec.Strategy // Set default DeploymentType as RollingUpdate. if strategy.Type == "" { strategy.Type = DeploymentRollingUpdate } if strategy.Type == DeploymentRollingUpdate { if strategy.RollingUpdate == nil { rollingUpdate := RollingUpdateDeployment{} strategy.RollingUpdate = &rollingUpdate } if strategy.RollingUpdate.MaxUnavailable == nil { // Set default MaxUnavailable as 1 by default. maxUnavailable := util.NewIntOrStringFromInt(1) strategy.RollingUpdate.MaxUnavailable = &maxUnavailable } if strategy.RollingUpdate.MaxSurge == nil { // Set default MaxSurge as 1 by default. maxSurge := util.NewIntOrStringFromInt(1) strategy.RollingUpdate.MaxSurge = &maxSurge } } if obj.Spec.UniqueLabelKey == nil { obj.Spec.UniqueLabelKey = new(string) *obj.Spec.UniqueLabelKey = "deployment.kubernetes.io/podTemplateHash" } }, ) }
func TestGetURLParts(t *testing.T) { testCases := []struct { probe *api.HTTPGetAction ok bool host string port int path string }{ {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromInt(-1), Path: ""}, false, "", -1, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromString(""), Path: ""}, false, "", -1, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromString("-1"), Path: ""}, false, "", -1, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromString("not-found"), Path: ""}, false, "", -1, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromString("found"), Path: ""}, true, "127.0.0.1", 93, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromInt(76), Path: ""}, true, "127.0.0.1", 76, ""}, {&api.HTTPGetAction{Host: "", Port: util.NewIntOrStringFromString("118"), Path: ""}, true, "127.0.0.1", 118, ""}, {&api.HTTPGetAction{Host: "hostname", Port: util.NewIntOrStringFromInt(76), Path: "path"}, true, "hostname", 76, "path"}, } for _, test := range testCases { state := api.PodStatus{PodIP: "127.0.0.1"} container := api.Container{ Ports: []api.ContainerPort{{Name: "found", ContainerPort: 93}}, LivenessProbe: &api.Probe{ Handler: api.Handler{ HTTPGet: test.probe, }, }, } scheme := test.probe.Scheme if scheme == "" { scheme = api.URISchemeHTTP } host := test.probe.Host if host == "" { host = state.PodIP } port, err := extractPort(test.probe.Port, container) if test.ok && err != nil { t.Errorf("Unexpected error: %v", err) } path := test.probe.Path if !test.ok && err == nil { t.Errorf("Expected error for %+v, got %s%s:%d/%s", test, scheme, host, port, path) } if test.ok { if host != test.host || port != test.port || path != test.path { t.Errorf("Expected %s:%d/%s, got %s:%d/%s", test.host, test.port, test.path, host, port, path) } } } }
func TestServiceRegistryIPReallocation(t *testing.T) { rest, _ := NewTestREST(t, nil) svc1 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, } 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 !makeIPNet(t).Contains(net.ParseIP(created_service_1.Spec.ClusterIP)) { t.Errorf("Unexpected ClusterIP: %s", created_service_1.Spec.ClusterIP) } _, err := rest.Delete(ctx, created_service_1.Name) if err != nil { t.Errorf("Unexpected error deleting service: %v", err) } svc2 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "bar"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, } 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 !makeIPNet(t).Contains(net.ParseIP(created_service_2.Spec.ClusterIP)) { t.Errorf("Unexpected ClusterIP: %s", created_service_2.Spec.ClusterIP) } }
func TestServiceStorageValidatesUpdate(t *testing.T) { ctx := api.NewDefaultContext() storage, registry := NewTestREST(t, nil) registry.CreateService(ctx, &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, }}, }, }) failureCases := map[string]api.Service{ "empty ID": { ObjectMeta: api.ObjectMeta{Name: ""}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, }, "invalid selector": { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"ThisSelectorFailsValidation": "ok"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, }, } for _, failureCase := range failureCases { c, created, err := storage.Update(ctx, &failureCase) if c != nil || created { t.Errorf("Expected nil object or created false") } if !errors.IsInvalid(err) { t.Errorf("Expected to get an invalid resource error, got %v", err) } } }
// createPortAndServiceSpec creates an array of service ports. // If the NodePort value is 0, just the servicePort is used, otherwise, a node port is exposed. func createPortAndServiceSpec(servicePort int, nodePort int) ([]api.ServicePort, api.ServiceType) { //Use the Cluster IP type for the service port if NodePort isn't provided. //Otherwise, we will be binding the master service to a NodePort. if nodePort <= 0 { return []api.ServicePort{{Protocol: api.ProtocolTCP, Port: servicePort, TargetPort: util.NewIntOrStringFromInt(servicePort)}}, api.ServiceTypeClusterIP } return []api.ServicePort{{Protocol: api.ProtocolTCP, Port: servicePort, TargetPort: util.NewIntOrStringFromInt(servicePort), NodePort: nodePort, }}, api.ServiceTypeNodePort }
func TestServiceRegistryUpdate(t *testing.T) { ctx := api.NewDefaultContext() storage, registry := NewTestREST(t, nil) svc, err := registry.CreateService(ctx, &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1", Namespace: api.NamespaceDefault}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz1"}, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, }) if err != nil { t.Fatalf("Expected no error: %v", err) } updated_svc, created, err := storage.Update(ctx, &api.Service{ ObjectMeta: api.ObjectMeta{ Name: "foo", ResourceVersion: svc.ResourceVersion}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz2"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, }) if err != nil { t.Fatalf("Expected no error: %v", err) } if updated_svc == nil { t.Errorf("Expected non-nil object") } if created { t.Errorf("expected not created") } updated_service := updated_svc.(*api.Service) if updated_service.Name != "foo" { t.Errorf("Expected foo, but got %v", updated_service.Name) } if e, a := "foo", registry.UpdatedID; e != a { t.Errorf("Expected %v, but got %v", e, a) } }
func TestSyncEndpointsItemsWithLabels(t *testing.T) { ns := "other" te := "other" testServer, endpointsHandler := makeTestServer(t, ns, te, serverResponse{http.StatusOK, &api.Endpoints{}}) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Default.Version()}) endpoints := NewEndpointController(client, controller.NoResyncPeriodFunc) addPods(endpoints.podStore.Store, ns, 3, 2, 0) serviceLabels := map[string]string{"foo": "bar"} endpoints.serviceStore.Store.Add(&api.Service{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, Tenant: te, Labels: serviceLabels, }, Spec: api.ServiceSpec{ Selector: map[string]string{"foo": "bar"}, Ports: []api.ServicePort{ {Name: "port0", Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8080)}, {Name: "port1", Port: 88, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8088)}, }, }, }) endpoints.syncService(ns + "/foo") expectedSubsets := []api.EndpointSubset{{ Addresses: []api.EndpointAddress{ {IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}, {IP: "1.2.3.5", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod1", Namespace: ns}}, {IP: "1.2.3.6", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod2", Namespace: ns}}, }, Ports: []api.EndpointPort{ {Name: "port0", Port: 8080, Protocol: "TCP"}, {Name: "port1", Port: 8088, Protocol: "TCP"}, }, }} data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ ObjectMeta: api.ObjectMeta{ ResourceVersion: "", Tenant: te, Labels: serviceLabels, }, Subsets: endptspkg.SortSubsets(expectedSubsets), }) // endpointsHandler should get 2 requests - one for "GET" and the next for "POST". endpointsHandler.ValidateRequestCount(t, 2) endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, ""), "POST", &data) }
func TestSetDefaulServiceTargetPort(t *testing.T) { in := &versioned.Service{Spec: versioned.ServiceSpec{Ports: []versioned.ServicePort{{Port: 1234}}}} obj := roundTrip(t, runtime.Object(in)) out := obj.(*versioned.Service) if out.Spec.Ports[0].TargetPort != util.NewIntOrStringFromInt(1234) { t.Errorf("Expected TargetPort to be defaulted, got %v", out.Spec.Ports[0].TargetPort) } in = &versioned.Service{Spec: versioned.ServiceSpec{Ports: []versioned.ServicePort{{Port: 1234, TargetPort: util.NewIntOrStringFromInt(5678)}}}} obj = roundTrip(t, runtime.Object(in)) out = obj.(*versioned.Service) if out.Spec.Ports[0].TargetPort != util.NewIntOrStringFromInt(5678) { t.Errorf("Expected TargetPort to be unchanged, got %v", out.Spec.Ports[0].TargetPort) } }
func TestCreate(t *testing.T) { storage, fakeClient := newStorage(t) test := registrytest.New(t, fakeClient, storage.Etcd) validService := validService() validService.ObjectMeta = api.ObjectMeta{} test.TestCreate( // valid validService, // invalid &api.Service{ Spec: api.ServiceSpec{}, }, // invalid &api.Service{ Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, ClusterIP: "invalid", SessionAffinity: "None", Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, }, ) }
func runServiceAndRCForResourceConsumer(c *client.Client, ns, name string, replicas int, cpuLimitMillis, memLimitMb int64) { By(fmt.Sprintf("Running consuming RC %s with %v replicas", name, replicas)) _, err := c.Services(ns).Create(&api.Service{ ObjectMeta: api.ObjectMeta{ Name: name, }, Spec: api.ServiceSpec{ Ports: []api.ServicePort{{ Port: port, TargetPort: util.NewIntOrStringFromInt(targetPort), }}, Selector: map[string]string{ "name": name, }, }, }) expectNoError(err) config := RCConfig{ Client: c, Image: resourceConsumerImage, Name: name, Namespace: ns, Timeout: timeoutRC, Replicas: replicas, CpuRequest: cpuLimitMillis, CpuLimit: cpuLimitMillis, MemRequest: memLimitMb * 1024 * 1024, // MemLimit is in bytes MemLimit: memLimitMb * 1024 * 1024, } expectNoError(RunRC(config)) // Make sure endpoints are propagated. // TODO(piosz): replace sleep with endpoints watch. time.Sleep(10 * time.Second) }
func TestUpdate(t *testing.T) { storage, fakeClient := newStorage(t) test := resttest.New(t, storage, fakeClient.SetError).AllowCreateOnUpdate() test.TestUpdate( // valid validService(), func(ctx api.Context, obj runtime.Object) error { return registrytest.SetObject(fakeClient, storage.KeyFunc, ctx, obj) }, func(resourceVersion uint64) { registrytest.SetResourceVersion(fakeClient, resourceVersion) }, func(ctx api.Context, obj runtime.Object) (runtime.Object, error) { return registrytest.GetObject(fakeClient, storage.KeyFunc, storage.NewFunc, ctx, obj) }, // updateFunc func(obj runtime.Object) runtime.Object { object := obj.(*api.Service) object.Spec = api.ServiceSpec{ Selector: map[string]string{"bar": "baz2"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, } return object }, ) }
// Creates a replication controller that serves its hostname and a service on top of it. func startServeHostnameService(c *client.Client, ns, name string, port, replicas int) ([]string, string, error) { podNames := make([]string, replicas) By("creating service " + name + " in namespace " + ns) _, err := c.Services(ns).Create(&api.Service{ ObjectMeta: api.ObjectMeta{ Name: name, }, Spec: api.ServiceSpec{ Ports: []api.ServicePort{{ Port: port, TargetPort: util.NewIntOrStringFromInt(9376), Protocol: "TCP", }}, Selector: map[string]string{ "name": name, }, }, }) if err != nil { return podNames, "", err } var createdPods []*api.Pod maxContainerFailures := 0 config := RCConfig{ Client: c, Image: "gcr.io/google_containers/serve_hostname:1.1", Name: name, Namespace: ns, PollInterval: 3 * time.Second, Timeout: podReadyBeforeTimeout, Replicas: replicas, CreatedPods: &createdPods, MaxContainerFailures: &maxContainerFailures, } err = RunRC(config) if err != nil { return podNames, "", err } if len(createdPods) != replicas { return podNames, "", fmt.Errorf("Incorrect number of running pods: %v", len(createdPods)) } for i := range createdPods { podNames[i] = createdPods[i].ObjectMeta.Name } sort.StringSlice(podNames).Sort() service, err := c.Services(ns).Get(name) if err != nil { return podNames, "", err } if service.Spec.ClusterIP == "" { return podNames, "", fmt.Errorf("Service IP is blank for %v", name) } serviceIP := service.Spec.ClusterIP return podNames, serviceIP, nil }
func TestServiceRegistryExternalService(t *testing.T) { ctx := api.NewDefaultContext() storage, registry := NewTestREST(t, nil) svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeLoadBalancer, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, } _, err := storage.Create(ctx, svc) if err != nil { t.Errorf("Failed to create service: %#v", err) } 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 runServiceAndRCForResourceConsumer(c *client.Client, ns, name string, replicas int, cpuLimitMillis, memLimitMb int64) { _, err := c.Services(ns).Create(&api.Service{ ObjectMeta: api.ObjectMeta{ Name: name, }, Spec: api.ServiceSpec{ Ports: []api.ServicePort{{ Port: port, TargetPort: util.NewIntOrStringFromInt(targetPort), }}, Selector: map[string]string{ "name": name, }, }, }) expectNoError(err) config := RCConfig{ Client: c, Image: image, Name: name, Namespace: ns, Timeout: timeoutRC, Replicas: replicas, CpuLimit: cpuLimitMillis, MemLimit: memLimitMb * 1024 * 1024, // MemLimit is in bytes } expectNoError(RunRC(config)) }
func TestServiceRegistryIPLoadBalancer(t *testing.T) { rest, _ := NewTestREST(t, nil) svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeLoadBalancer, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, } ctx := api.NewDefaultContext() created_svc, _ := rest.Create(ctx, svc) created_service := created_svc.(*api.Service) if created_service.Spec.Ports[0].Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Ports[0].Port) } if !makeIPNet(t).Contains(net.ParseIP(created_service.Spec.ClusterIP)) { t.Errorf("Unexpected ClusterIP: %s", created_service.Spec.ClusterIP) } update := deepCloneService(created_service) _, _, err := rest.Update(ctx, update) if err != nil { t.Errorf("Unexpected error %v", err) } }
func TestSyncEndpointsItemsPreexistingIdentical(t *testing.T) { ns := api.NamespaceDefault te := api.TenantDefault testServer, endpointsHandler := makeTestServer(t, api.NamespaceDefault, te, serverResponse{http.StatusOK, &api.Endpoints{ ObjectMeta: api.ObjectMeta{ ResourceVersion: "1", Name: "foo", Namespace: ns, Tenant: te, }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, }}, }}) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Default.Version()}) endpoints := NewEndpointController(client, controller.NoResyncPeriodFunc) addPods(endpoints.podStore.Store, api.NamespaceDefault, 1, 1, 0) endpoints.serviceStore.Store.Add(&api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, Spec: api.ServiceSpec{ Selector: map[string]string{"foo": "bar"}, Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8080)}}, }, }) endpoints.syncService(ns + "/foo") endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", api.NamespaceDefault, "foo"), "GET", nil) }
func TestCreate(t *testing.T) { storage, fakeClient := newStorage(t) test := resttest.New(t, storage, fakeClient.SetError) validService := validService() validService.ObjectMeta = api.ObjectMeta{} test.TestCreate( // valid validService, func(ctx api.Context, obj runtime.Object) error { return registrytest.SetObject(fakeClient, storage.KeyFunc, ctx, obj) }, func(ctx api.Context, obj runtime.Object) (runtime.Object, error) { return registrytest.GetObject(fakeClient, storage.KeyFunc, storage.NewFunc, ctx, obj) }, // invalid &api.Service{ Spec: api.ServiceSpec{}, }, // invalid &api.Service{ Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, ClusterIP: "invalid", SessionAffinity: "None", Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, }, ) }
func startService(c *client.Client, ns, name string, replicas int) { c.Services(ns).Create(&api.Service{ ObjectMeta: api.ObjectMeta{ Name: name, }, Spec: api.ServiceSpec{ Ports: []api.ServicePort{{ Port: port, TargetPort: util.NewIntOrStringFromInt(targetPort), }}, Selector: map[string]string{ "name": name, }, }, }) config := RCConfig{ Client: c, Image: image, Name: name, Namespace: ns, Timeout: timeoutRC, Replicas: replicas, } expectNoError(RunRC(config)) }
func (b webserverProbeBuilder) build() *api.Probe { probe := &api.Probe{ Handler: api.Handler{ HTTPGet: &api.HTTPGetAction{ Port: util.NewIntOrStringFromInt(80), Path: "/", }, }, } if b.initialDelay { probe.InitialDelaySeconds = 30 } if b.failing { probe.HTTPGet.Port = util.NewIntOrStringFromInt(81) } return probe }
func TestDoRequestNewWayFile(t *testing.T) { reqObj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} reqBodyExpected, err := testapi.Codec().Encode(reqObj) if err != nil { t.Errorf("unexpected error: %v", err) } file, err := ioutil.TempFile("", "foo") if err != nil { t.Errorf("unexpected error: %v", err) } _, err = file.Write(reqBodyExpected) if err != nil { t.Errorf("unexpected error: %v", err) } expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: util.NewIntOrStringFromInt(12345), }}}} expectedBody, _ := testapi.Codec().Encode(expectedObj) fakeHandler := util.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) c := NewOrDie(&Config{Host: testServer.URL, Version: testapi.Version(), Username: "******", Password: "******"}) wasCreated := true obj, err := c.Verb("POST"). Prefix("foo/bar", "baz"). Timeout(time.Second). Body(file.Name()). Do().WasCreated(&wasCreated).Get() if err != nil { t.Errorf("Unexpected error: %v %#v", err, err) return } if obj == nil { t.Error("nil obj") } else if !api.Semantic.DeepDerivative(expectedObj, obj) { t.Errorf("Expected: %#v, got %#v", expectedObj, obj) } if wasCreated { t.Errorf("expected object was not created") } tmpStr := string(reqBodyExpected) requestURL := testapi.ResourcePathWithPrefix("foo/bar/baz", "", "", "") requestURL += "?timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) if fakeHandler.RequestReceived.Header["Authorization"] == nil { t.Errorf("Request is missing authorization header: %#v", *fakeHandler.RequestReceived) } }
func TestSetDefaultServicePort(t *testing.T) { // Unchanged if set. in := &versioned.Service{Spec: versioned.ServiceSpec{ Ports: []versioned.ServicePort{ {Protocol: "UDP", Port: 9376, TargetPort: util.NewIntOrStringFromString("p")}, {Protocol: "UDP", Port: 8675, TargetPort: util.NewIntOrStringFromInt(309)}, }, }} out := roundTrip(t, runtime.Object(in)).(*versioned.Service) if out.Spec.Ports[0].Protocol != versioned.ProtocolUDP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolUDP, out.Spec.Ports[0].Protocol) } if out.Spec.Ports[0].TargetPort != util.NewIntOrStringFromString("p") { t.Errorf("Expected port %v, got %v", in.Spec.Ports[0].Port, out.Spec.Ports[0].TargetPort) } if out.Spec.Ports[1].Protocol != versioned.ProtocolUDP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolUDP, out.Spec.Ports[1].Protocol) } if out.Spec.Ports[1].TargetPort != util.NewIntOrStringFromInt(309) { t.Errorf("Expected port %v, got %v", in.Spec.Ports[1].Port, out.Spec.Ports[1].TargetPort) } // Defaulted. in = &versioned.Service{Spec: versioned.ServiceSpec{ Ports: []versioned.ServicePort{ {Protocol: "", Port: 9376, TargetPort: util.NewIntOrStringFromString("")}, {Protocol: "", Port: 8675, TargetPort: util.NewIntOrStringFromInt(0)}, }, }} out = roundTrip(t, runtime.Object(in)).(*versioned.Service) if out.Spec.Ports[0].Protocol != versioned.ProtocolTCP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Spec.Ports[0].Protocol) } if out.Spec.Ports[0].TargetPort != util.NewIntOrStringFromInt(in.Spec.Ports[0].Port) { t.Errorf("Expected port %v, got %v", in.Spec.Ports[0].Port, out.Spec.Ports[0].TargetPort) } if out.Spec.Ports[1].Protocol != versioned.ProtocolTCP { t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Spec.Ports[1].Protocol) } if out.Spec.Ports[1].TargetPort != util.NewIntOrStringFromInt(in.Spec.Ports[1].Port) { t.Errorf("Expected port %v, got %v", in.Spec.Ports[1].Port, out.Spec.Ports[1].TargetPort) } }
func TestServiceRegistryIPUpdate(t *testing.T) { rest, _ := NewTestREST(t, nil) svc := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{ Port: 6502, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(6502), }}, }, } ctx := api.NewDefaultContext() created_svc, _ := rest.Create(ctx, svc) created_service := created_svc.(*api.Service) if created_service.Spec.Ports[0].Port != 6502 { t.Errorf("Expected port 6502, but got %v", created_service.Spec.Ports[0].Port) } if !makeIPNet(t).Contains(net.ParseIP(created_service.Spec.ClusterIP)) { t.Errorf("Unexpected ClusterIP: %s", created_service.Spec.ClusterIP) } update := deepCloneService(created_service) update.Spec.Ports[0].Port = 6503 updated_svc, _, _ := rest.Update(ctx, update) updated_service := updated_svc.(*api.Service) if updated_service.Spec.Ports[0].Port != 6503 { t.Errorf("Expected port 6503, but got %v", updated_service.Spec.Ports[0].Port) } testIPs := []string{"1.2.3.93", "1.2.3.94", "1.2.3.95", "1.2.3.96"} testIP := "" for _, ip := range testIPs { if !rest.serviceIPs.(*ipallocator.Range).Has(net.ParseIP(ip)) { testIP = ip break } } update = deepCloneService(created_service) update.Spec.Ports[0].Port = 6503 update.Spec.ClusterIP = testIP // Error: Cluster IP is immutable _, _, err := rest.Update(ctx, update) if err == nil || !errors.IsInvalid(err) { t.Errorf("Unexpected error type: %v", err) } }
func makeTestService(name string) *api.Service { return &api.Service{ ObjectMeta: api.ObjectMeta{Name: name, Namespace: "default"}, Spec: api.ServiceSpec{ Ports: []api.ServicePort{ {Name: "port", Protocol: api.ProtocolTCP, Port: 12345, TargetPort: util.NewIntOrStringFromInt(12345)}, }, Type: api.ServiceTypeClusterIP, SessionAffinity: api.ServiceAffinityNone, }, } }
func TestGetTCPAddrParts(t *testing.T) { testCases := []struct { probe *api.TCPSocketAction ok bool host string port int }{ {&api.TCPSocketAction{Port: util.NewIntOrStringFromInt(-1)}, false, "", -1}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromString("")}, false, "", -1}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromString("-1")}, false, "", -1}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromString("not-found")}, false, "", -1}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromString("found")}, true, "1.2.3.4", 93}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromInt(76)}, true, "1.2.3.4", 76}, {&api.TCPSocketAction{Port: util.NewIntOrStringFromString("118")}, true, "1.2.3.4", 118}, } for _, test := range testCases { host := "1.2.3.4" container := api.Container{ Ports: []api.ContainerPort{{Name: "found", ContainerPort: 93}}, LivenessProbe: &api.Probe{ Handler: api.Handler{ TCPSocket: test.probe, }, }, } port, err := extractPort(test.probe.Port, container) if !test.ok && err == nil { t.Errorf("Expected error for %+v, got %s:%d", test, host, port) } if test.ok && err != nil { t.Errorf("Unexpected error: %v", err) } if test.ok { if host != test.host || port != test.port { t.Errorf("Expected %s:%d, got %s:%d", test.host, test.port, host, port) } } } }
// TestUpdate_progressTimeout ensures that an update which isn't making any // progress will eventually time out with a specified error. func TestUpdate_progressTimeout(t *testing.T) { oldRc := oldRc(2, 2) newRc := newRc(0, 2) updater := &RollingUpdater{ ns: "default", scaleAndWait: func(rc *api.ReplicationController, retry *RetryParams, wait *RetryParams) (*api.ReplicationController, error) { // Do nothing. return rc, nil }, getOrCreateTargetController: func(controller *api.ReplicationController, sourceId string) (*api.ReplicationController, bool, error) { return newRc, false, nil }, cleanup: func(oldRc, newRc *api.ReplicationController, config *RollingUpdaterConfig) error { return nil }, } updater.waitForReadyPods = func(interval, timeout time.Duration, oldRc, newRc *api.ReplicationController) (int, int, error) { // Coerce a timeout by pods never becoming ready. return 0, 0, nil } var buffer bytes.Buffer config := &RollingUpdaterConfig{ Out: &buffer, OldRc: oldRc, NewRc: newRc, UpdatePeriod: 0, Interval: time.Millisecond, Timeout: time.Millisecond, CleanupPolicy: DeleteRollingUpdateCleanupPolicy, MaxUnavailable: util.NewIntOrStringFromInt(0), MaxSurge: util.NewIntOrStringFromInt(1), } err := updater.Update(config) if err == nil { t.Fatalf("expected an error") } if e, a := "timed out waiting for any update progress to be made", err.Error(); e != a { t.Fatalf("expected error message: %s, got: %s", e, a) } }
func TestSyncEndpointsItemsPreexistingLabelsChange(t *testing.T) { ns := "bar" te := "bar" testServer, endpointsHandler := makeTestServer(t, ns, te, serverResponse{http.StatusOK, &api.Endpoints{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, Tenant: te, ResourceVersion: "1", Labels: map[string]string{ "foo": "bar", }, }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, Ports: []api.EndpointPort{{Port: 1000}}, }}, }}) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Default.Version()}) endpoints := NewEndpointController(client, controller.NoResyncPeriodFunc) addPods(endpoints.podStore.Store, ns, 1, 1, 0) serviceLabels := map[string]string{"baz": "blah"} endpoints.serviceStore.Store.Add(&api.Service{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, Tenant: te, Labels: serviceLabels, }, Spec: api.ServiceSpec{ Selector: map[string]string{"foo": "bar"}, Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8080)}}, }, }) endpoints.syncService(ns + "/foo") data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, Tenant: te, ResourceVersion: "1", Labels: serviceLabels, }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, }}, }) endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, "foo"), "PUT", &data) }
// buildTestLoadBalancer build a common loadBalancerController to be used // in the tests to verify the generated HAProxy configuration file func buildTestLoadBalancer(lbDefAlgorithm string) *loadBalancerController { endpointAddresses := []api.EndpointAddress{ {IP: "1.2.3.4"}, {IP: "5.6.7.8"}, } ports := []int{80, 443} endpointPorts := []api.EndpointPort{ {Port: ports[0], Protocol: "TCP"}, {Port: ports[1], Protocol: "HTTP"}, } servicePorts := []api.ServicePort{ {Port: 10, TargetPort: util.NewIntOrStringFromInt(ports[0])}, {Port: 20, TargetPort: util.NewIntOrStringFromInt(ports[1])}, } svc1 := getService(servicePorts) svc1.ObjectMeta.Name = "svc-1" svc2 := getService(servicePorts) svc2.ObjectMeta.Name = "svc-2" endpoints := []*api.Endpoints{ getEndpoints(svc1, endpointAddresses, endpointPorts), getEndpoints(svc2, endpointAddresses, endpointPorts), } flb := newFakeLoadBalancerController(endpoints, []*api.Service{svc1, svc2}) cfg, _ := filepath.Abs("./test-samples/loadbalancer_test.json") // do not have the input parameters. We need to specify a default. if lbDefAlgorithm == "" { lbDefAlgorithm = "roundrobin" } flb.cfg = parseCfg(cfg, lbDefAlgorithm) cfgFile, _ := filepath.Abs("test-" + string(util.NewUUID())) flb.cfg.Config = cfgFile flb.tcpServices = map[string]int{ svc1.Name: 20, } return flb }
func TestGetEndpoints(t *testing.T) { // 2 pods each of which have 3 targetPorts exposed via a single service endpointAddresses := []api.EndpointAddress{ {IP: "1.2.3.4"}, {IP: "6.7.8.9"}, } ports := []int{80, 443, 3306} endpointPorts := []api.EndpointPort{ {Port: ports[0], Protocol: "TCP"}, {Port: ports[1], Protocol: "TCP"}, {Port: ports[2], Protocol: "TCP", Name: "mysql"}, } servicePorts := []api.ServicePort{ {Port: 10, TargetPort: util.NewIntOrStringFromInt(ports[0])}, {Port: 20, TargetPort: util.NewIntOrStringFromInt(ports[1])}, {Port: 30, TargetPort: util.NewIntOrStringFromString("mysql")}, } svc := getService(servicePorts) endpoints := []*api.Endpoints{getEndpoints(svc, endpointAddresses, endpointPorts)} flb := newFakeLoadBalancerController(endpoints, []*api.Service{svc}) for i := range ports { eps := flb.getEndpoints(svc, &svc.Spec.Ports[i]) expectedEps := sets.NewString() for _, address := range endpointAddresses { expectedEps.Insert(fmt.Sprintf("%v:%v", address.IP, ports[i])) } receivedEps := sets.NewString() for _, ep := range eps { receivedEps.Insert(ep) } if len(receivedEps) != len(expectedEps) || !expectedEps.IsSuperset(receivedEps) { t.Fatalf("Unexpected endpoints, received %+v, expected %+v", receivedEps, expectedEps) } glog.Infof("Got endpoints %+v", receivedEps) } }