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)
	}
}
Exemple #2
0
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)
	}
}
Exemple #3
0
// 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))
	}

}
Exemple #7
0
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
}