func TestEtcdUpdateService(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.TestIndex = true resp, _ := fakeClient.Set("/registry/services/specs/foo", util.MakeJSONString(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) testService := api.Service{ JSONBase: api.JSONBase{ID: "foo", ResourceVersion: resp.Node.ModifiedIndex}, Labels: map[string]string{ "baz": "bar", }, Selector: map[string]string{ "baz": "bar", }, } err := registry.UpdateService(testService) if err != nil { t.Errorf("unexpected error: %v", err) } svc, err := registry.GetService("foo") if err != nil { t.Errorf("unexpected error: %v", err) } // Clear modified indices before the equality test. svc.ResourceVersion = 0 testService.ResourceVersion = 0 if !reflect.DeepEqual(*svc, testService) { t.Errorf("Unexpected service: got\n %#v\n, wanted\n %#v", svc, testService) } }
func TestEtcdUpdateService(t *testing.T) { ctx := api.NewDefaultContext() fakeClient := tools.NewFakeEtcdClient(t) fakeClient.TestIndex = true registry := NewTestEtcdRegistry(fakeClient) key, _ := makeServiceKey(ctx, "uniquefoo") key = etcdtest.AddPrefix(key) resp, _ := fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, &api.Service{ObjectMeta: api.ObjectMeta{Name: "uniquefoo"}}), 0) testService := api.Service{ ObjectMeta: api.ObjectMeta{ Name: "uniquefoo", ResourceVersion: strconv.FormatUint(resp.Node.ModifiedIndex, 10), Labels: map[string]string{ "baz": "bar", }, }, Spec: api.ServiceSpec{ Selector: map[string]string{ "baz": "bar", }, SessionAffinity: "None", Type: api.ServiceTypeClusterIP, }, } _, err := registry.UpdateService(ctx, &testService) if err != nil { t.Errorf("unexpected error: %v", err) } svc, err := registry.GetService(ctx, "uniquefoo") if err != nil { t.Errorf("unexpected error: %v", err) } // Clear modified indices before the equality test. svc.ResourceVersion = "" testService.ResourceVersion = "" if !api.Semantic.DeepEqual(*svc, testService) { t.Errorf("Unexpected service: got\n %#v\n, wanted\n %#v", svc, testService) } }
// ValidateService tests if required fields in the service are set. func ValidateService(service *api.Service) errs.ErrorList { allErrs := errs.ErrorList{} if len(service.ID) == 0 { allErrs = append(allErrs, errs.NewFieldRequired("id", service.ID)) } else if !util.IsDNS952Label(service.ID) { allErrs = append(allErrs, errs.NewFieldInvalid("id", service.ID)) } if !util.IsValidPortNum(service.Port) { allErrs = append(allErrs, errs.NewFieldInvalid("Service.Port", service.Port)) } if len(service.Protocol) == 0 { service.Protocol = "TCP" } else if !supportedPortProtocols.Has(strings.ToUpper(service.Protocol)) { allErrs = append(allErrs, errs.NewFieldNotSupported("protocol", service.Protocol)) } if labels.Set(service.Selector).AsSelector().Empty() { allErrs = append(allErrs, errs.NewFieldRequired("selector", service.Selector)) } return allErrs }
func (sr *ServiceRegistryStorage) Extract(body string) (interface{}, error) { var svc api.Service err := json.Unmarshal([]byte(body), &svc) svc.Kind = "cluster#service" return svc, err }
func runAtomicPutTest(c *client.Client) { var svc api.Service err := c.Post().Path("services").Body( api.Service{ JSONBase: api.JSONBase{ID: "atomicservice", APIVersion: "v1beta1"}, Port: 12345, Labels: map[string]string{ "name": "atomicService", }, // This is here because validation requires it. Selector: map[string]string{ "foo": "bar", }, }, ).Do().Into(&svc) 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) var tmpSvc api.Service err := c.Get(). Path("services"). Path(svc.ID). PollPeriod(100 * time.Millisecond). Do(). Into(&tmpSvc) if err != nil { glog.Errorf("Error getting atomicService: %v", err) continue } if tmpSvc.Selector == nil { tmpSvc.Selector = map[string]string{l: v} } else { tmpSvc.Selector[l] = v } glog.Infof("Posting update (%s, %s)", l, v) err = c.Put().Path("services").Path(svc.ID).Body(&tmpSvc).Do().Error() if err != nil { if se, ok := err.(*client.StatusErr); ok { if se.Status.Code == http.StatusConflict { 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() if err := c.Get().Path("services").Path(svc.ID).Do().Into(&svc); err != nil { glog.Fatalf("Failed getting atomicService after writers are complete: %v", err) } if !reflect.DeepEqual(testLabels, labels.Set(svc.Selector)) { glog.Fatalf("Selector PUTs were not atomic: wanted %v, got %v", testLabels, svc.Selector) } glog.Info("Atomic PUTs work.") }
func TestServiceUpdateLabel(t *testing.T) { kube := mocks.NewKubeClient() client := new(contrail_mocks.ApiClient) client.Init() client.AddInterceptor("virtual-machine-interface", &VmiInterceptor{}) client.AddInterceptor("virtual-network", &NetworkInterceptor{}) client.AddInterceptor("instance-ip", &IpInterceptor{}) client.AddInterceptor("floating-ip", &FloatingIpInterceptor{}) controller := NewTestController(kube, client, nil, nil) pod1 := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "test-sv1", Namespace: "testns", UID: kubetypes.UID(uuid.New()), Labels: map[string]string{ "name": "server", }, }, } pod2 := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "test-xz2", Namespace: "testns", UID: kubetypes.UID(uuid.New()), Labels: map[string]string{ "name": "client1", "uses": "red", }, }, } pod3 := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "test-xz3", Namespace: "testns", UID: kubetypes.UID(uuid.New()), Labels: map[string]string{ "name": "client2", "uses": "blue", }, }, } service := &api.Service{ ObjectMeta: api.ObjectMeta{ Name: "service", Namespace: "testns", Labels: map[string]string{ "name": "red", }, }, Spec: api.ServiceSpec{ Selector: map[string]string{ "name": "server", }, ClusterIP: "10.254.42.42", Type: api.ServiceTypeLoadBalancer, }, } netnsProject := new(types.Project) netnsProject.SetFQName("", []string{"default-domain", "testns"}) client.Create(netnsProject) kube.PodInterface.On("Update", pod1).Return(pod1, nil) kube.PodInterface.On("Update", pod2).Return(pod2, nil) kube.PodInterface.On("Update", pod3).Return(pod3, nil) selectServer := labels.Set(map[string]string{"name": "server"}).AsSelector() kube.PodInterface.On("List", selectServer, mock.Anything).Return(&api.PodList{Items: []api.Pod{*pod1}}, nil) kube.ServiceInterface.On("Update", service).Return(service, nil) shutdown := make(chan struct{}) go controller.Run(shutdown) controller.AddPod(pod1) controller.AddPod(pod2) controller.AddPod(pod3) controller.AddService(service) time.Sleep(100 * time.Millisecond) redPolicy, err := types.NetworkPolicyByName(client, "default-domain:testns:red") assert.NoError(t, err) if err == nil { assert.Len(t, redPolicy.GetNetworkPolicyEntries().PolicyRule, 1) assert.True(t, policyHasRule(redPolicy, "default-domain:testns:client1", "default-domain:testns:service-red")) refs, err := redPolicy.GetVirtualNetworkBackRefs() assert.NoError(t, err) nameList := getReferenceListNames(refs) assert.Contains(t, nameList, "default-domain:testns:client1") assert.Contains(t, nameList, "default-domain:testns:service-red") } bluePolicy, err := types.NetworkPolicyByName(client, "default-domain:testns:blue") assert.NoError(t, err) if err == nil { assert.Len(t, bluePolicy.GetNetworkPolicyEntries().PolicyRule, 0) refs, err := bluePolicy.GetVirtualNetworkBackRefs() assert.NoError(t, err) assert.Len(t, refs, 1) } nService := new(api.Service) *nService = *service nService.Labels = map[string]string{ "name": "blue", } // The service will receive a different PublicIP because this is translated into a service delete operation, // followed by an add. kube.ServiceInterface.On("Update", nService).Return(nService, nil) controller.UpdateService(service, nService) time.Sleep(100 * time.Millisecond) type shutdownMsg struct { } shutdown <- shutdownMsg{} bluePolicy, err = types.NetworkPolicyByName(client, "default-domain:testns:blue") assert.NoError(t, err) if err == nil { assert.Len(t, bluePolicy.GetNetworkPolicyEntries().PolicyRule, 1) assert.True(t, policyHasRule(bluePolicy, "default-domain:testns:client2", "default-domain:testns:service-blue")) refs, err := bluePolicy.GetVirtualNetworkBackRefs() assert.NoError(t, err) nameList := getReferenceListNames(refs) assert.Contains(t, nameList, "default-domain:testns:client2") assert.Contains(t, nameList, "default-domain:testns:service-blue") } redPolicy, err = types.NetworkPolicyByName(client, "default-domain:testns:red") assert.NoError(t, err) if err == nil { assert.Len(t, redPolicy.GetNetworkPolicyEntries().PolicyRule, 0) refs, err := redPolicy.GetVirtualNetworkBackRefs() assert.NoError(t, err) assert.Len(t, refs, 1) } fip, err := types.FloatingIpByName(client, "default-domain:testns:service-blue:service-blue:service") assert.NoError(t, err) if err == nil { vmList, err := getFloatingIpToInstanceList(client, fip) assert.NoError(t, err) assert.Len(t, vmList, 1) assert.Contains(t, vmList, string(pod1.UID)) } }
func (self *realKubeFramework) CreateService(ns string, service *api.Service) (*api.Service, error) { service.Namespace = ns newSvc, err := self.kubeClient.Services(ns).Create(service) return newSvc, err }