func runMasterServiceTest(client *client.Client) { time.Sleep(12 * time.Second) svcList, err := client.Services(api.NamespaceDefault).List(labels.Everything()) if err != nil { glog.Fatalf("unexpected error listing services: %v", err) } var foundRW bool found := util.StringSet{} for i := range svcList.Items { found.Insert(svcList.Items[i].Name) if svcList.Items[i].Name == "qingyuan" { foundRW = true } } if foundRW { ep, err := client.Endpoints(api.NamespaceDefault).Get("qingyuan") if err != nil { glog.Fatalf("unexpected error listing endpoints for qingyuan service: %v", err) } if countEndpoints(ep) == 0 { glog.Fatalf("no endpoints for qingyuan service: %v", ep) } } else { glog.Errorf("no RW service found: %v", found) glog.Fatal("QingYuan service test failed") } glog.Infof("Master service test passed.") }
func expectedServicesExist(c *client.Client) error { serviceList, err := c.Services(api.NamespaceDefault).List(labels.Everything()) if err != nil { return err } for _, service := range serviceList.Items { if _, ok := expectedServices[service.Name]; ok { expectedServices[service.Name] = true } } for service, found := range expectedServices { if !found { return fmt.Errorf("Service %q not found", service) } } return nil }
func waitForLoadBalancerDestroy(c *client.Client, serviceName, namespace string) (*api.Service, error) { // TODO: once support ticket 21807001 is resolved, reduce this timeout back to something reasonable const timeout = 10 * time.Minute var service *api.Service By(fmt.Sprintf("waiting up to %v for service %s in namespace %s to have no LoadBalancer ingress points", timeout, serviceName, namespace)) for start := time.Now(); time.Since(start) < timeout; time.Sleep(5 * time.Second) { service, err := c.Services(namespace).Get(serviceName) if err != nil { Logf("Get service failed, ignoring for 5s: %v", err) continue } if len(service.Status.LoadBalancer.Ingress) == 0 { return service, nil } Logf("Waiting for service %s in namespace %s to have no LoadBalancer ingress points (%v)", serviceName, namespace, time.Since(start)) } return service, fmt.Errorf("service %s in namespace %s still has LoadBalancer ingress points after %.2f seconds", serviceName, namespace, timeout.Seconds()) }
Expect(err).NotTo(HaveOccurred()) namespaces[i] = namespacePtr.Name } }) AfterEach(func() { for _, ns := range namespaces { By(fmt.Sprintf("Destroying namespace %v", ns)) if err := c.Namespaces().Delete(ns); err != nil { Failf("Couldn't delete namespace %s: %s", ns, err) } } }) // TODO: We get coverage of TCP/UDP and multi-port services through the DNS test. We should have a simpler test for multi-port TCP here. It("should provide secure master service", func() { _, err := c.Services(api.NamespaceDefault).Get("qingyuan") Expect(err).NotTo(HaveOccurred()) }) It("should serve a basic endpoint from pods", func() { serviceName := "endpoint-test2" ns := namespaces[0] labels := map[string]string{ "foo": "bar", "baz": "blah", } defer func() { err := c.Services(ns).Delete(serviceName) Expect(err).NotTo(HaveOccurred()) }()
Name: svcName, Labels: map[string]string{ "name": svcName, }, }, Spec: api.ServiceSpec{ Ports: []api.ServicePort{{ Port: 8765, TargetPort: util.NewIntOrStringFromInt(8080), }}, Selector: map[string]string{ "name": serverName, }, }, } defer c.Services(api.NamespaceDefault).Delete(svc.Name) _, err = c.Services(api.NamespaceDefault).Create(svc) if err != nil { Fail(fmt.Sprintf("Failed to create service: %v", err)) } // Make a client pod that verifies that it has the service environment variables. podName := "client-envvars-" + string(util.NewUUID()) pod := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: podName, Labels: map[string]string{"name": podName}, }, Spec: api.PodSpec{ Containers: []api.Container{ {
func runServiceTest(client *client.Client) { pod := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Labels: map[string]string{ "name": "thisisalonglabel", }, }, Spec: api.PodSpec{ Containers: []api.Container{ { Name: "c1", Image: "foo", Ports: []api.ContainerPort{ {ContainerPort: 1234}, }, ImagePullPolicy: api.PullIfNotPresent, }, }, RestartPolicy: api.RestartPolicyAlways, DNSPolicy: api.DNSClusterFirst, }, Status: api.PodStatus{ PodIP: "1.2.3.4", }, } pod, err := client.Pods(api.NamespaceDefault).Create(pod) if err != nil { glog.Fatalf("Failed to create pod: %v, %v", pod, err) } if err := wait.Poll(time.Second, time.Second*20, podExists(client, pod.Namespace, pod.Name)); err != nil { glog.Fatalf("FAILED: pod never started running %v", err) } svc1 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "service1"}, Spec: api.ServiceSpec{ Selector: map[string]string{ "name": "thisisalonglabel", }, Ports: []api.ServicePort{{ Port: 8080, Protocol: "TCP", }}, SessionAffinity: "None", }, } svc1, err = client.Services(api.NamespaceDefault).Create(svc1) if err != nil { glog.Fatalf("Failed to create service: %v, %v", svc1, err) } // create an identical service in the non-default namespace svc3 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "service1"}, Spec: api.ServiceSpec{ Selector: map[string]string{ "name": "thisisalonglabel", }, Ports: []api.ServicePort{{ Port: 8080, Protocol: "TCP", }}, SessionAffinity: "None", }, } svc3, err = client.Services("other").Create(svc3) if err != nil { glog.Fatalf("Failed to create service: %v, %v", svc3, err) } // TODO Reduce the timeouts in this test when endpoints controller is sped up. See #6045. if err := wait.Poll(time.Second, time.Second*60, endpointsSet(client, svc1.Namespace, svc1.Name, 1)); err != nil { glog.Fatalf("FAILED: unexpected endpoints: %v", err) } // A second service with the same port. svc2 := &api.Service{ ObjectMeta: api.ObjectMeta{Name: "service2"}, Spec: api.ServiceSpec{ Selector: map[string]string{ "name": "thisisalonglabel", }, Ports: []api.ServicePort{{ Port: 8080, Protocol: "TCP", }}, SessionAffinity: "None", }, } svc2, err = client.Services(api.NamespaceDefault).Create(svc2) if err != nil { glog.Fatalf("Failed to create service: %v, %v", svc2, err) } if err := wait.Poll(time.Second, time.Second*60, endpointsSet(client, svc2.Namespace, svc2.Name, 1)); err != nil { glog.Fatalf("FAILED: unexpected endpoints: %v", err) } if err := wait.Poll(time.Second, time.Second*60, endpointsSet(client, svc3.Namespace, svc3.Name, 0)); err != nil { glog.Fatalf("FAILED: service in other namespace should have no endpoints: %v", err) } svcList, err := client.Services(api.NamespaceAll).List(labels.Everything()) if err != nil { glog.Fatalf("Failed to list services across namespaces: %v", err) } names := util.NewStringSet() for _, svc := range svcList.Items { names.Insert(fmt.Sprintf("%s/%s", svc.Namespace, svc.Name)) } if !names.HasAll("default/qingyuan", "default/service1", "default/service2", "other/service1") { glog.Fatalf("Unexpected service list: %#v", names) } glog.Info("Service test passed.") }
func runPatchTest(c *client.Client) { name := "patchservice" resource := "services" svcBody := api.Service{ TypeMeta: api.TypeMeta{ APIVersion: c.APIVersion(), }, ObjectMeta: api.ObjectMeta{ Name: name, Labels: map[string]string{}, }, Spec: api.ServiceSpec{ // This is here because validation requires it. Selector: map[string]string{ "foo": "bar", }, Ports: []api.ServicePort{{ Port: 12345, Protocol: "TCP", }}, SessionAffinity: "None", }, } services := c.Services(api.NamespaceDefault) svc, err := services.Create(&svcBody) if err != nil { glog.Fatalf("Failed creating patchservice: %v", err) } patchBodies := map[string]map[api.PatchType]struct { AddLabelBody []byte RemoveLabelBody []byte RemoveAllLabelsBody []byte }{ "v1beta3": { api.JSONPatchType: { []byte(`[{"op":"add","path":"/metadata/labels","value":{"foo":"bar","baz":"qux"}}]`), []byte(`[{"op":"remove","path":"/metadata/labels/foo"}]`), []byte(`[{"op":"remove","path":"/metadata/labels"}]`), }, api.MergePatchType: { []byte(`{"metadata":{"labels":{"foo":"bar","baz":"qux"}}}`), []byte(`{"metadata":{"labels":{"foo":null}}}`), []byte(`{"metadata":{"labels":null}}`), }, api.StrategicMergePatchType: { []byte(`{"metadata":{"labels":{"foo":"bar","baz":"qux"}}}`), []byte(`{"metadata":{"labels":{"foo":null}}}`), []byte(`{"metadata":{"labels":{"$patch":"replace"}}}`), }, }, "v1": { api.JSONPatchType: { []byte(`[{"op":"add","path":"/metadata/labels","value":{"foo":"bar","baz":"qux"}}]`), []byte(`[{"op":"remove","path":"/metadata/labels/foo"}]`), []byte(`[{"op":"remove","path":"/metadata/labels"}]`), }, api.MergePatchType: { []byte(`{"metadata":{"labels":{"foo":"bar","baz":"qux"}}}`), []byte(`{"metadata":{"labels":{"foo":null}}}`), []byte(`{"metadata":{"labels":null}}`), }, api.StrategicMergePatchType: { []byte(`{"metadata":{"labels":{"foo":"bar","baz":"qux"}}}`), []byte(`{"metadata":{"labels":{"foo":null}}}`), []byte(`{"metadata":{"labels":{"$patch":"replace"}}}`), }, }, } pb := patchBodies[c.APIVersion()] execPatch := func(pt api.PatchType, body []byte) error { return c.Patch(pt). Resource(resource). Namespace(api.NamespaceDefault). Name(name). Body(body). Do(). Error() } for k, v := range pb { // add label err := execPatch(k, v.AddLabelBody) if err != nil { glog.Fatalf("Failed updating patchservice with patch type %s: %v", k, err) } svc, err = services.Get(name) if err != nil { glog.Fatalf("Failed getting patchservice: %v", err) } if len(svc.Labels) != 2 || svc.Labels["foo"] != "bar" || svc.Labels["baz"] != "qux" { glog.Fatalf("Failed updating patchservice with patch type %s: labels are: %v", k, svc.Labels) } // remove one label err = execPatch(k, v.RemoveLabelBody) if err != nil { glog.Fatalf("Failed updating patchservice with patch type %s: %v", k, err) } svc, err = services.Get(name) if err != nil { glog.Fatalf("Failed getting patchservice: %v", err) } if len(svc.Labels) != 1 || svc.Labels["baz"] != "qux" { glog.Fatalf("Failed updating patchservice with patch type %s: labels are: %v", k, svc.Labels) } // remove all labels err = execPatch(k, v.RemoveAllLabelsBody) if err != nil { glog.Fatalf("Failed updating patchservice with patch type %s: %v", k, err) } svc, err = services.Get(name) if err != nil { glog.Fatalf("Failed getting patchservice: %v", err) } if svc.Labels != nil { glog.Fatalf("Failed remove all labels from patchservice with patch type %s: %v", k, svc.Labels) } } glog.Info("PATCHs work.") }
func runAtomicPutTest(c *client.Client) { svcBody := api.Service{ TypeMeta: api.TypeMeta{ APIVersion: c.APIVersion(), }, ObjectMeta: api.ObjectMeta{ Name: "atomicservice", Labels: map[string]string{ "name": "atomicService", }, }, Spec: api.ServiceSpec{ // This is here because validation requires it. Selector: map[string]string{ "foo": "bar", }, Ports: []api.ServicePort{{ Port: 12345, Protocol: "TCP", }}, SessionAffinity: "None", }, } services := c.Services(api.NamespaceDefault) svc, err := services.Create(&svcBody) if err != nil { glog.Fatalf("Failed creating atomicService: %v", err) } glog.Info("Created atomicService") testLabels := labels.Set{ "foo": "bar", } for i := 0; i < 5; i++ { // a: z, b: y, etc... testLabels[string([]byte{byte('a' + i)})] = string([]byte{byte('z' - i)}) } var wg sync.WaitGroup wg.Add(len(testLabels)) for label, value := range testLabels { go func(l, v string) { for { glog.Infof("Starting to update (%s, %s)", l, v) tmpSvc, err := services.Get(svc.Name) if err != nil { glog.Errorf("Error getting atomicService: %v", err) continue } if tmpSvc.Spec.Selector == nil { tmpSvc.Spec.Selector = map[string]string{l: v} } else { tmpSvc.Spec.Selector[l] = v } glog.Infof("Posting update (%s, %s)", l, v) tmpSvc, err = services.Update(tmpSvc) if err != nil { if apierrors.IsConflict(err) { glog.Infof("Conflict: (%s, %s)", l, v) // This is what we expect. continue } glog.Errorf("Unexpected error putting atomicService: %v", err) continue } break } glog.Infof("Done update (%s, %s)", l, v) wg.Done() }(label, value) } wg.Wait() svc, err = services.Get(svc.Name) if err != nil { glog.Fatalf("Failed getting atomicService after writers are complete: %v", err) } if !reflect.DeepEqual(testLabels, labels.Set(svc.Spec.Selector)) { glog.Fatalf("Selector PUTs were not atomic: wanted %v, got %v", testLabels, svc.Spec.Selector) } glog.Info("Atomic PUTs work.") }
func runSelfLinkTestOnNamespace(c *client.Client, namespace string) { svcBody := api.Service{ ObjectMeta: api.ObjectMeta{ Name: "selflinktest", Namespace: namespace, Labels: map[string]string{ "name": "selflinktest", }, }, Spec: api.ServiceSpec{ // This is here because validation requires it. Selector: map[string]string{ "foo": "bar", }, Ports: []api.ServicePort{{ Port: 12345, Protocol: "TCP", }}, SessionAffinity: "None", }, } services := c.Services(namespace) svc, err := services.Create(&svcBody) if err != nil { glog.Fatalf("Failed creating selflinktest service: %v", err) } err = c.Get().RequestURI(svc.SelfLink).Do().Into(svc) if err != nil { glog.Fatalf("Failed listing service with supplied self link '%v': %v", svc.SelfLink, err) } svcList, err := services.List(labels.Everything()) if err != nil { glog.Fatalf("Failed listing services: %v", err) } err = c.Get().RequestURI(svcList.SelfLink).Do().Into(svcList) if err != nil { glog.Fatalf("Failed listing services with supplied self link '%v': %v", svcList.SelfLink, err) } found := false for i := range svcList.Items { item := &svcList.Items[i] if item.Name != "selflinktest" { continue } found = true err = c.Get().RequestURI(item.SelfLink).Do().Into(svc) if err != nil { glog.Fatalf("Failed listing service with supplied self link '%v': %v", item.SelfLink, err) } break } if !found { glog.Fatalf("never found selflinktest service in namespace %s", namespace) } glog.Infof("Self link test passed in namespace %s", namespace) // TODO: Should test PUT at some point, too. }