Пример #1
0
func TestReadChildren(t *testing.T) {
	client := new(ApiClient)
	client.Init()

	project := new(types.Project)
	project.SetFQName("domain", []string{"default-domain", "p1"})
	assert.NoError(t, client.Create(project))

	net := new(types.VirtualNetwork)
	net.SetFQName("project", []string{"default-domain", "p1", "n1"})
	assert.NoError(t, client.Create(net))

	vmi1 := new(types.VirtualMachineInterface)
	vmi1.SetFQName("project", []string{"default-domain", "p1", "port1"})
	vmi1.AddVirtualNetwork(net)
	assert.NoError(t, client.Create(vmi1))

	vmi2 := new(types.VirtualMachineInterface)
	vmi2.SetFQName("project", []string{"default-domain", "p1", "port2"})
	vmi2.AddVirtualNetwork(net)
	assert.NoError(t, client.Create(vmi2))

	refs, err := project.GetVirtualMachineInterfaces()
	assert.NoError(t, err)
	assert.Len(t, refs, 2)
}
Пример #2
0
func (m *ApiClient) Init() {
	m.db = NewInMemDatabase()

	m.updater = NewObjectUpdater(m.db)

	domain := new(types.Domain)
	domain.SetName("default-domain")
	err := m.Create(domain)
	if err != nil {
		panic(err.Error())
	}

	project := new(types.Project)
	project.SetFQName("domain", []string{"default-domain", "default-project"})
	err = m.Create(project)
	if err != nil {
		panic(err.Error())
	}

	ipam := new(types.NetworkIpam)
	ipam.SetFQName("project", []string{"default-domain", "default-project", "default-network-ipam"})
	err = m.Create(ipam)
	if err != nil {
		panic(err.Error())
	}
}
func TestConsistencyStaleVM(t *testing.T) {
	env := new(TestFramework)
	env.SetUp("192.0.2.0/24")
	client := env.client

	netnsProject := new(types.Project)
	netnsProject.SetFQName("domain", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	env.Start()
	installPods(env, "testns", 3)
	env.SyncBarrier()
	env.Shutdown()

	assert.True(t, env.checker.Check())

	p2 := new(types.Project)
	p2.SetFQName("domain", []string{"default-domain", "p2"})
	assert.NoError(t, client.Create(p2))

	vm := new(types.VirtualMachine)
	vm.SetFQName("project", []string{"default-domain", "p2", "x"})
	assert.NoError(t, client.Create(vm))
	assert.False(t, env.checker.Check())

	assert.NoError(t, client.Delete(vm))
	assert.True(t, env.checker.Check())

	vm = new(types.VirtualMachine)
	vm.SetFQName("project", []string{"default-domain", "testns", "pod03"})
	assert.NoError(t, client.Create(vm))
	assert.False(t, env.checker.Check())
}
Пример #4
0
func TestListByParent(t *testing.T) {
	client := new(ApiClient)
	client.Init()

	projectNames := []string{"p1", "p2", "p3"}
	vmNames := []string{"a", "b", "c", "d"}

	for _, projectName := range projectNames {
		project := new(types.Project)
		project.SetFQName("domain", []string{"default-domain", projectName})
		assert.NoError(t, client.Create(project))

		for _, vmName := range vmNames {
			vm := new(types.VirtualMachine)
			vm.SetFQName("project", []string{"default-domain", projectName, vmName})
			assert.NoError(t, client.Create(vm))
		}
	}

	elements, err := client.ListByParent("virtual-machine", "default-domain:p2")
	assert.NoError(t, err)
	for _, element := range elements {
		assert.Equal(t, "p2", element.Fq_name[1])
	}
}
func TestNamespaceDelete(t *testing.T) {
	client := new(contrail_mocks.ApiClient)
	client.Init()
	allocator := new(mocks.AddressAllocator)
	networkMgr := new(mocks.NetworkManager)
	controller := NewTestController(nil, client, allocator, networkMgr)

	namespace := &api.Namespace{
		ObjectMeta: api.ObjectMeta{
			Name: "netns",
			UID:  kubetypes.UID(uuid.New()),
		},
	}

	project := new(types.Project)
	project.SetFQName("domain", []string{DefaultDomain, "netns"})
	project.SetUuid(string(namespace.ObjectMeta.UID))
	client.Create(project)

	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	controller.DeleteNamespace(namespace)

	time.Sleep(100 * time.Millisecond)
	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}

	_, err := client.FindByUuid("project", string(namespace.ObjectMeta.UID))
	assert.NotNil(t, err)
}
func TestConsistencyStaleInterface(t *testing.T) {
	client := createTestClient()
	podStore := new(mocks.Store)
	serviceStore := new(mocks.Store)
	checker := NewConsistencyChecker(client, NewConfig(), podStore, serviceStore, nil)

	kube := mocks.NewKubeClient()
	controller := NewTestController(kube, client, nil, nil)

	netnsProject := new(types.Project)
	netnsProject.SetFQName("domain", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	installPods(controller, &kube.PodInterface.Mock, &podStore.Mock, "testns", 3)
	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	time.Sleep(100 * time.Millisecond)
	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}
	time.Sleep(100 * time.Millisecond)

	serviceStore.On("List").Return([]interface{}{})
	assert.True(t, checker.Check())

	vmi := new(types.VirtualMachineInterface)
	vmi.SetFQName("project", []string{"default-domain", "testns", "pod03"})
	assert.NoError(t, client.Create(vmi))

	assert.False(t, checker.Check())
}
func TestConsistencyMissingInterface(t *testing.T) {
	env := new(TestFramework)
	env.SetUp("192.0.2.0/24")
	client := env.client

	netnsProject := new(types.Project)
	netnsProject.SetFQName("domain", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	env.Start()
	installPods(env, "testns", 3)
	env.SyncBarrier()
	env.Shutdown()

	assert.True(t, env.checker.Check())

	vmi, err := types.VirtualMachineInterfaceByName(client, "default-domain:testns:pod01")
	assert.NoError(t, err)
	refs, err := vmi.GetInstanceIpBackRefs()
	for _, ref := range refs {
		ip, err := types.InstanceIpByUuid(client, ref.Uuid)
		assert.NoError(t, err)
		ip.ClearVirtualMachineInterface()
		assert.NoError(t, client.Update(ip))
	}
	assert.NoError(t, client.Delete(vmi))

	assert.False(t, env.checker.Check())
}
func TestPodUsesNonExistingService(t *testing.T) {
	kube := mocks.NewKubeClient()

	client := new(contrail_mocks.ApiClient)
	client.Init()

	client.AddInterceptor("virtual-machine-interface", &VmiInterceptor{})
	client.AddInterceptor("virtual-network", &NetworkInterceptor{})

	allocator := new(mocks.AddressAllocator)

	controller := NewTestController(kube, client, allocator, nil)

	pod1 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-xz1",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"name": "testpod",
				"uses": "nonexisting",
			},
		},
	}

	netnsProject := new(types.Project)
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	allocator.On("LocateIpAddress", string(pod1.ObjectMeta.UID)).Return("10.0.0.1", nil)
	allocator.On("ReleaseIpAddress", string(pod1.ObjectMeta.UID)).Return()
	kube.PodInterface.On("Update", pod1).Return(pod1, nil)

	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	controller.AddPod(pod1)
	time.Sleep(100 * time.Millisecond)

	_, err := types.NetworkPolicyByName(client, "default-domain:testns:nonexisting")
	assert.NoError(t, err)

	_, err = types.VirtualNetworkByName(client, "default-domain:testns:testpod")
	assert.NoError(t, err)

	controller.DeletePod(pod1)
	time.Sleep(100 * time.Millisecond)
	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}

	_, err = types.VirtualNetworkByName(client, "default-domain:testns:testpod")
	assert.Error(t, err)

	_, err = types.NetworkPolicyByName(client, "default-domain:testns:nonexisting")
	assert.Error(t, err)

	allocator.AssertExpectations(t)
}
func (t *TestFramework) SetUp(publicSubnet string) {
	t.client = new(contrail_mocks.ApiClient)
	t.client.Init()

	t.client.AddInterceptor("virtual-machine-interface", &VmiInterceptor{})
	t.client.AddInterceptor("virtual-network", &NetworkInterceptor{})
	t.client.AddInterceptor("instance-ip", &IpInterceptor{})
	t.client.AddInterceptor("floating-ip", &FloatingIpInterceptor{})

	t.podStore = new(mocks.Store)
	t.serviceStore = new(mocks.Store)

	t.kubeMock = mocks.NewKubeClient()
	t.config = NewConfig()
	t.config.PublicSubnet = publicSubnet
	t.controller = makeSyncController(t.kubeMock, t.config)
	t.controller.SetPodStore(t.podStore)
	t.controller.SetServiceStore(t.serviceStore)
	t.controller.initComponents(t.client)

	t.checker = t.controller.newConsistencyChecker()

	for _, projectName := range testProjects {
		project := new(types.Project)
		project.SetFQName("domain", []string{t.config.DefaultDomain, projectName})
		t.client.Create(project)
	}

	t.state = make(map[string]*TestGroupState, 0)
	t.clusterIPs = make(map[int]string, 0)
	t.keyList = make([]string, 0)

	t.shutdown = make(chan struct{})

	keysCall := t.podStore.On("ListKeys").Return()
	keysCall.Run(func(arg mock.Arguments) {
		keysCall.Return(t.keyList)
	})

	listCall := t.serviceStore.On("List").Return()
	listCall.Run(func(arg mock.Arguments) {
		serviceList := make([]interface{}, 0)
		for _, v := range t.state {
			for _, svc := range v.Services {
				serviceList = append(serviceList, svc)
			}
		}
		listCall.Return(serviceList)
	})
}
func TestPodCreate(t *testing.T) {
	kube := mocks.NewKubeClient()

	client := new(contrail_mocks.ApiClient)
	client.Init()

	client.AddInterceptor("virtual-machine-interface", &VmiInterceptor{})
	allocator := new(mocks.AddressAllocator)
	networkMgr := new(mocks.NetworkManager)

	controller := NewTestController(kube, client, allocator, networkMgr)
	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"name": "testnet",
			},
		},
	}

	netnsProject := new(types.Project)
	netnsProject.SetUuid(uuid.New())
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	testnet := new(types.VirtualNetwork)
	testnet.SetFQName("project", []string{"default-domain", "testns", "testnet"})
	client.Create(testnet)

	allocator.On("LocateIpAddress", string(pod.ObjectMeta.UID)).Return("10.0.0.42", nil)
	networkMgr.On("LocateNetwork", "testns", "testnet",
		controller.config.PrivateSubnet).Return(testnet, nil)
	networkMgr.On("GetGatewayAddress", testnet).Return("10.0.255.254", nil)

	kube.PodInterface.On("Update", pod).Return(pod, nil)

	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	controller.AddPod(pod)

	time.Sleep(100 * time.Millisecond)
	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}

	kube.PodInterface.AssertExpectations(t)
}
Пример #11
0
func (m *NamespaceManager) LocateNamespace(name, uid string) *types.Project {
	fqn := []string{DefaultDomain, name}

	obj, err := m.client.FindByName("project", strings.Join(fqn, ":"))
	if err == nil {
		return obj.(*types.Project)
	}
	project := new(types.Project)
	project.SetFQName("domain", fqn)
	project.SetUuid(uid)
	err = m.client.Create(project)
	if err != nil {
		glog.Errorf("Create project %s: %v", name, err)
	}
	return project
}
Пример #12
0
func TestReadModifiedPolicy(t *testing.T) {
	client := new(ApiClient)
	client.Init()

	project := new(types.Project)
	project.SetFQName("domain", []string{"default-domain", "p1"})
	assert.NoError(t, client.Create(project))

	policy := new(types.NetworkPolicy)
	policy.SetFQName("project", []string{"default-domain", "p1", "x"})
	assert.NoError(t, client.Create(policy))

	net1 := new(types.VirtualNetwork)
	net1.SetFQName("project", []string{"default-domain", "p1", "n1"})
	net1.AddNetworkPolicy(policy,
		types.VirtualNetworkPolicyType{
			Sequence: &types.SequenceType{10, 0},
		})
	assert.NoError(t, client.Create(net1))

	net2 := new(types.VirtualNetwork)
	net2.SetFQName("project", []string{"default-domain", "p1", "n2"})
	net2.AddNetworkPolicy(policy,
		types.VirtualNetworkPolicyType{
			Sequence: &types.SequenceType{10, 0},
		})
	assert.NoError(t, client.Create(net2))

	refs, err := policy.GetVirtualNetworkBackRefs()
	assert.NoError(t, err)
	assert.Len(t, refs, 2)

	assert.NoError(t, client.Delete(net1))

	refs, err = policy.GetVirtualNetworkBackRefs()
	assert.NoError(t, err)
	assert.Len(t, refs, 1)

	assert.NoError(t, client.Delete(net2))
	refs, err = policy.GetVirtualNetworkBackRefs()
	assert.NoError(t, err)
	assert.Len(t, refs, 0)
}
Пример #13
0
func TestNetworkLocate(t *testing.T) {
	client := new(contrail_mocks.ApiClient)
	client.Init()

	config := new(Config)
	config.PublicNetwork = "default-domain:default-project:Public"
	netman := NewNetworkManager(client, config)

	project := new(types.Project)
	project.SetUuid(uuid.New())
	project.SetFQName("", []string{config.DefaultDomain, "p1"})
	client.Create(project)

	network, err := netman.LocateNetwork("p1", "n1", "10.0.1.0/24")
	assert.NoError(t, err, "LocateNetwork")

	n2, err := netman.LocateNetwork("p1", "n1", "10.0.1.0/24")
	assert.NoError(t, err, "LocateNetwork -- exists")
	assert.Equal(t, network, n2)
}
func TestConsistencyMissingInterface(t *testing.T) {
	client := createTestClient()
	podStore := new(mocks.Store)
	serviceStore := new(mocks.Store)
	checker := NewConsistencyChecker(client, NewConfig(), podStore, serviceStore, nil)

	kube := mocks.NewKubeClient()
	controller := NewTestController(kube, client, nil, nil)

	netnsProject := new(types.Project)
	netnsProject.SetFQName("domain", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	installPods(controller, &kube.PodInterface.Mock, &podStore.Mock, "testns", 3)
	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	time.Sleep(100 * time.Millisecond)
	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}
	time.Sleep(100 * time.Millisecond)

	serviceStore.On("List").Return([]interface{}{})
	assert.True(t, checker.Check())

	vmi, err := types.VirtualMachineInterfaceByName(client, "default-domain:testns:pod01")
	assert.NoError(t, err)
	refs, err := vmi.GetInstanceIpBackRefs()
	for _, ref := range refs {
		ip, err := types.InstanceIpByUuid(client, ref.Uuid)
		assert.NoError(t, err)
		ip.ClearVirtualMachineInterface()
		assert.NoError(t, client.Update(ip))
	}
	assert.NoError(t, client.Delete(vmi))

	assert.False(t, checker.Check())
}
Пример #15
0
func TestUpdateClearVM(t *testing.T) {
	client := new(ApiClient)
	client.Init()

	project := new(types.Project)
	project.SetFQName("domain", []string{"default-domain", "tenant"})
	assert.NoError(t, client.Create(project))

	vm := new(types.VirtualMachine)
	vm.SetFQName("project", []string{"default-domain", "tenant", "instance"})
	assert.NoError(t, client.Create(vm))

	vmi := new(types.VirtualMachineInterface)
	vmi.SetFQName("project", []string{"default-domain", "tenant", "instance"})
	vmi.AddVirtualMachine(vm)
	assert.NoError(t, client.Create(vmi))

	vmi.ClearVirtualMachine()
	assert.NoError(t, client.Update(vmi))

	assert.NoError(t, client.Delete(vm))
}
Пример #16
0
func TestReadRefs(t *testing.T) {
	client := new(ApiClient)
	client.Init()

	project := new(types.Project)
	project.SetFQName("domain", []string{"default-domain", "p1"})
	assert.NoError(t, client.Create(project))

	net := new(types.VirtualNetwork)
	net.SetFQName("project", []string{"default-domain", "p1", "n1"})
	assert.NoError(t, client.Create(net))

	vmi1 := new(types.VirtualMachineInterface)
	vmi1.SetFQName("project", []string{"default-domain", "p1", "port1"})
	vmi1.AddVirtualNetwork(net)
	assert.NoError(t, client.Create(vmi1))

	refs, err := vmi1.GetVirtualNetworkRefs()
	assert.NoError(t, err)
	assert.Len(t, refs, 1)
	assert.Equal(t, net.GetUuid(), refs[0].Uuid)
}
Пример #17
0
func TestReadBackRefs(t *testing.T) {
	client := new(ApiClient)
	client.Init()

	project := new(types.Project)
	project.SetFQName("domain", []string{"default-domain", "p1"})
	assert.NoError(t, client.Create(project))

	net := new(types.VirtualNetwork)
	net.SetFQName("project", []string{"default-domain", "p1", "n1"})
	props := new(types.VirtualNetworkType)
	props.ForwardingMode = "turbo"
	net.SetVirtualNetworkProperties(props)
	assert.NoError(t, client.Create(net))

	vmi1 := new(types.VirtualMachineInterface)
	vmi1.SetFQName("project", []string{"default-domain", "p1", "port1"})
	vmi1.AddVirtualNetwork(net)
	assert.NoError(t, client.Create(vmi1))

	vmi2 := new(types.VirtualMachineInterface)
	vmi2.SetFQName("project", []string{"default-domain", "p1", "port2"})
	vmi2.AddVirtualNetwork(net)
	assert.NoError(t, client.Create(vmi2))

	refs, err := net.GetVirtualMachineInterfaceBackRefs()
	assert.NoError(t, err)
	assert.Len(t, refs, 2)
	idList := make([]string, len(refs))
	for i, ref := range refs {
		idList[i] = ref.Uuid
	}

	assert.Contains(t, idList, vmi1.GetUuid())
	assert.Contains(t, idList, vmi2.GetUuid())

	rProps := net.GetVirtualNetworkProperties()
	assert.Equal(t, "turbo", rProps.ForwardingMode)
}
func TestGlobalNetworkConsistencyUpdateNetwork(t *testing.T) {
	env := new(TestFramework)
	env.SetUp("192.0.2.0/24")

	config := env.config
	config.GlobalNetworks = []string{"default-domain:cluster:global"}

	pod1 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-xz1",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":            "server",
				config.NetworkTag: "backend",
			},
		},
	}
	pod2 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-xz2",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":                  "client",
				config.NetworkTag:       "client",
				config.NetworkAccessTag: "svc",
			},
		},
	}
	pod3 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "gPod",
			Namespace: "cluster",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":            "global",
				config.NetworkTag: "global",
			},
		},
	}

	service := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s1",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "svc",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"Name": "server",
			},
			ClusterIP: "10.254.42.42",
		},
	}

	clusterProject := new(types.Project)
	clusterProject.SetFQName("", []string{"default-domain", "cluster"})
	require.NoError(t, env.client.Create(clusterProject))

	netnsProject := new(types.Project)
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	require.NoError(t, env.client.Create(netnsProject))

	env.Start()

	env.AddPod(pod1)
	env.AddPod(pod2)
	env.AddPod(pod3)
	env.AddService(service, "server")
	env.SyncBarrier()

	// This connects the global-network policy with the respective network which is created after
	// the policy.
	assert.False(t, env.checker.Check())
	// It should be ok now.
	assert.True(t, env.checker.Check())

	policyName := makeGlobalNetworkPolicyName(config, []string{"default-domain", "cluster", "global"})
	policy, err := types.NetworkPolicyByName(env.client, strings.Join(policyName, ":"))
	require.NoError(t, err)

	netRefs, err := policy.GetVirtualNetworkBackRefs()
	require.NoError(t, err)
	assert.Len(t, netRefs, 3)
	assert.Len(t, policy.GetNetworkPolicyEntries().PolicyRule, 2)

	env.DeletePod(pod1)
	env.DeletePod(pod2)
	env.DeleteService(service, "server")
	env.SyncBarrier()

	_, err = types.NetworkPolicyByName(env.client, strings.Join(policyName, ":"))
	assert.Error(t, err)

	assert.True(t, env.checker.Check())

	env.Shutdown()
}
func TestPodAddWithService(t *testing.T) {
	kube := mocks.NewKubeClient()

	client := new(contrail_mocks.ApiClient)
	client.Init()

	client.AddInterceptor("virtual-machine-interface", &VmiInterceptor{})
	client.AddInterceptor("virtual-network", &NetworkInterceptor{})

	allocator := new(mocks.AddressAllocator)

	controller := NewTestController(kube, client, allocator, nil)
	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"name": "testpod",
			},
		},
	}
	service := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s1",
			Namespace: "testns",
			Labels: map[string]string{
				"name": "x1",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"name": "testpod",
			},
			ClusterIP: "10.254.42.42",
		},
	}

	netnsProject := new(types.Project)
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	allocator.On("LocateIpAddress", string(pod.ObjectMeta.UID)).Return("10.0.0.1", nil)

	kube.PodInterface.On("Update", pod).Return(pod, nil)

	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	controller.serviceStore.Add(service)
	controller.AddPod(pod)

	time.Sleep(100 * time.Millisecond)
	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}

	kube.PodInterface.AssertExpectations(t)

	obj, err := client.FindByName("virtual-network", "default-domain:testns:service-x1")
	assert.NoError(t, err)
	serviceNet := obj.(*types.VirtualNetwork)
	sip, err := controller.networkMgr.LocateFloatingIp(serviceNet, service.Name, service.Spec.ClusterIP)
	assert.NoError(t, err)
	refList, err := sip.GetVirtualMachineInterfaceRefs()
	assert.Nil(t, err)
	assert.NotEmpty(t, refList)
}
func TestConsistencyConnectionsDelete(t *testing.T) {
	podStore := new(mocks.Store)
	serviceStore := new(mocks.Store)

	kube := mocks.NewKubeClient()
	client := createTestClient()
	controller := NewTestController(kube, client, nil, nil)
	config := controller.config
	controller.SetPodStore(podStore)
	controller.SetServiceStore(serviceStore)

	checker := NewConsistencyChecker(client, controller.config, podStore, serviceStore, controller.serviceMgr)

	controller.config.ClusterServices = []string{"kube-system/dns", "kube-system/monitoring"}

	// 2 client pods in network "private"
	pod1 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "pod01",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				config.NetworkTag:       "private",
				config.NetworkAccessTag: "tagA",
			},
		},
	}

	pod2 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "pod02",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				config.NetworkTag:       "private",
				config.NetworkAccessTag: "tagB",
			},
		},
	}

	// The service pods for service tagA and tagB respectivly.
	pod3 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "pod03",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				config.NetworkTag: "svc-backend",
				"app":             "provider01",
			},
		},
	}

	pod4 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "pod04",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				config.NetworkTag: "svc-backend",
				"app":             "provider02",
			},
		},
	}

	// And the services
	service1 := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "service1",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "tagA",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"app": "provider01",
			},
			ClusterIP: "10.254.42.42",
			Type:      api.ServiceTypeClusterIP,
		},
	}

	service2 := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "service1",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "tagB",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"app": "provider02",
			},
			ClusterIP: "10.254.42.43",
			Type:      api.ServiceTypeClusterIP,
		},
	}

	netnsProject := new(types.Project)
	netnsProject.SetFQName("domain", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	sysProject := new(types.Project)
	sysProject.SetFQName("domain", []string{"default-domain", "kube-system"})
	client.Create(sysProject)

	keys := make([]string, 0)
	addPod(pod1, kube.PodInterface, podStore, &keys)
	addPod(pod2, kube.PodInterface, podStore, &keys)
	addPod(pod3, kube.PodInterface, podStore, &keys)
	addPod(pod4, kube.PodInterface, podStore, &keys)
	podStore.On("ListKeys").Return(keys).Once()

	serviceStore.On("List").Return([]interface{}{service1, service2})

	s1Pods := makeListOptSelector(map[string]string{"app": "provider01"})
	kube.PodInterface.On("List", s1Pods).Return(&api.PodList{Items: []api.Pod{*pod3}}, nil)

	s2Pods := makeListOptSelector(map[string]string{"app": "provider02"})
	kube.PodInterface.On("List", s2Pods).Return(&api.PodList{Items: []api.Pod{*pod4}}, nil)

	kube.ServiceInterface.On("Update", service1).Return(service1, nil)
	kube.ServiceInterface.On("Update", service2).Return(service2, nil)

	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	controller.AddPod(pod1)
	controller.AddPod(pod2)
	controller.AddPod(pod3)
	controller.AddPod(pod4)
	controller.AddService(service1)
	controller.AddService(service2)

	time.Sleep(100 * time.Millisecond)
	assert.True(t, checker.Check())

	controller.DeletePod(pod2)
	time.Sleep(100 * time.Millisecond)
	keys = append(keys[0:1], keys[2:]...)
	podStore.On("ListKeys").Return(keys)

	assert.False(t, checker.Check())
	assert.False(t, checker.Check())
	assert.True(t, checker.Check())

	config.ClusterServices = []string{"kube-system/dns"}

	assert.False(t, checker.Check())
	assert.False(t, checker.Check())
	assert.True(t, checker.Check())

	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}
}
func TestServiceDeleteWithPod(t *testing.T) {
	kube := mocks.NewKubeClient()

	client := new(contrail_mocks.ApiClient)
	client.Init()

	client.AddInterceptor("virtual-machine-interface", &VmiInterceptor{})
	client.AddInterceptor("virtual-network", &NetworkInterceptor{})

	allocator := new(mocks.AddressAllocator)

	controller := NewTestController(kube, client, allocator, nil)

	pod1 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-xz1",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"name": "testpod",
			},
		},
	}
	pod2 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-xz2",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"name": "testpod",
			},
		},
	}

	service := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s1",
			Namespace: "testns",
			Labels: map[string]string{
				"name": "x1",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"name": "testpod",
			},
			ClusterIP: "10.254.42.42",
		},
	}

	netnsProject := new(types.Project)
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	allocator.On("LocateIpAddress", string(pod1.ObjectMeta.UID)).Return("10.0.0.1", nil)
	allocator.On("LocateIpAddress", string(pod2.ObjectMeta.UID)).Return("10.0.0.2", nil)

	kube.PodInterface.On("Update", pod1).Return(pod1, nil)
	kube.PodInterface.On("Update", pod2).Return(pod2, nil)
	kube.PodInterface.On("List", mock.Anything, mock.Anything).Return(&api.PodList{Items: []api.Pod{*pod1, *pod2}}, nil)

	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	controller.AddPod(pod1)
	controller.AddPod(pod2)
	controller.AddService(service)

	time.Sleep(100 * time.Millisecond)

	obj, err := client.FindByName("virtual-network", "default-domain:testns:service-x1")
	assert.NoError(t, err)
	serviceNet := obj.(*types.VirtualNetwork)
	sip, err := controller.networkMgr.LocateFloatingIp(serviceNet, service.Name, service.Spec.ClusterIP)
	sipName := sip.GetFQName()
	assert.NoError(t, err)
	refList, err := sip.GetVirtualMachineInterfaceRefs()
	assert.Nil(t, err)
	assert.NotEmpty(t, refList)

	obj, err = client.FindByName("network-policy", "default-domain:testns:x1")
	assert.NoError(t, err)

	controller.DeleteService(service)
	time.Sleep(100 * time.Millisecond)
	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}

	obj, err = client.FindByName("virtual-network", "default-domain:testns:service-x1")
	assert.Error(t, err)

	obj, err = client.FindByName("floating-ip", strings.Join(sipName, ":"))
	assert.Error(t, err)

	obj, err = client.FindByName("network-policy", "default-domain:testns:x1")
	assert.Error(t, err)
}
Пример #22
0
func TestServiceDeleteConnections(t *testing.T) {
	client := new(contrail_mocks.ApiClient)
	client.Init()

	config := NewConfig()
	networkMgr := NewNetworkManager(client, config)
	serviceMgr := NewServiceManager(client, config, networkMgr)

	netnsProject := new(types.Project)
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	globalProject := new(types.Project)
	globalProject.SetFQName("", []string{"default-domain", "global"})
	client.Create(globalProject)

	network, err := networkMgr.LocateNetwork("testns", "client", config.PrivateSubnet)

	services := []string{
		"testns/s1",
		"testns/s2",
		"global/s3",
		"global/s4",
	}

	for _, svc := range services {
		parts := strings.Split(svc, "/")
		namespace := parts[0]
		svcName := parts[1]
		err := serviceMgr.Create(namespace, svcName)
		if err != nil {
			t.Error(err)
			continue
		}
		err = serviceMgr.Connect(namespace, svcName, network)
		if err != nil {
			t.Error(err)
		}
	}

	serviceList := MakeServiceIdList()
	serviceList.Add("testns", "s1")
	serviceList.Add("global", "s3")

	purgeList := make([]string, 0)
	policyRefs, err := network.GetNetworkPolicyRefs()
	require.NoError(t, err)
	for _, ref := range policyRefs {
		require.Len(t, ref.To, 3)
		svcName, err := serviceNameFromPolicyName(ref.To[2])
		require.NoError(t, err)
		if serviceList.Contains(ref.To[1], svcName) {
			continue
		}
		purgeList = append(purgeList, ref.Uuid)
	}

	err = serviceMgr.DeleteConnections(network, purgeList)
	if err != nil {
		t.Fatal(err)
	}

	refs, err := network.GetNetworkPolicyRefs()
	if err != nil {
		t.Fatal(err)
	}
	if len(refs) != len(serviceList) {
		t.Errorf("expected %d policy refs, got %d", len(serviceList), len(refs))
	}
	actual := make([]string, 0)
	for _, ref := range refs {
		svc, err := serviceNameFromPolicyName(ref.To[2])
		if err != nil {
			continue
		}
		actual = append(actual, ref.To[1]+"/"+svc)
	}
	assert.EqualValues(t, []string{"testns/s1", "global/s3"}, actual)
}
func TestGlobalNetworkConsistencyConfigChange(t *testing.T) {
	env := new(TestFramework)
	env.SetUp("192.0.2.0/24")

	config := env.config
	config.GlobalNetworks = []string{"default-domain:cluster:global"}

	pod1 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-xz1",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":            "server",
				config.NetworkTag: "backend",
			},
		},
	}
	pod2 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-xz2",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":                  "client",
				config.NetworkTag:       "client",
				config.NetworkAccessTag: "svc",
			},
		},
	}
	pod3 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "gPod",
			Namespace: "cluster",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":            "global",
				config.NetworkTag: "global",
			},
		},
	}

	service := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s1",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "svc",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"Name": "server",
			},
			ClusterIP: "10.254.42.42",
		},
	}

	clusterProject := new(types.Project)
	clusterProject.SetFQName("", []string{"default-domain", "cluster"})
	require.NoError(t, env.client.Create(clusterProject))

	netnsProject := new(types.Project)
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	require.NoError(t, env.client.Create(netnsProject))

	env.Start()

	env.AddPod(pod3)
	env.AddPod(pod1)
	env.AddPod(pod2)
	env.AddService(service, "server")
	env.SyncBarrier()

	assert.True(t, env.checker.Check())

	config.GlobalNetworks = []string{}
	for i := 0; i < 2; i++ {
		assert.False(t, env.checker.Check())
	}

	assert.True(t, env.checker.Check())

	policyName := makeGlobalNetworkPolicyName(config, []string{"default-domain", "cluster", "global"})
	_, err := types.NetworkPolicyByName(env.client, strings.Join(policyName, ":"))
	require.Error(t, err)

	env.DeletePod(pod1)
	env.DeletePod(pod2)
	env.DeletePod(pod3)
	env.DeleteService(service, "server")
	env.SyncBarrier()

	env.Shutdown()

	assert.True(t, env.checker.Check())
}
func TestConsistencyMissingVM(t *testing.T) {
	client := createTestClient()
	podStore := new(mocks.Store)
	serviceStore := new(mocks.Store)
	checker := NewConsistencyChecker(client, NewConfig(), podStore, serviceStore, nil, nil)

	pod1 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-sv1",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
		},
	}
	pod2 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-sv2",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
		},
	}

	kube := mocks.NewKubeClient()
	controller := NewTestController(kube, client, nil, nil)

	netnsProject := new(types.Project)
	netnsProject.SetFQName("domain", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	kube.Pods("testns").(*mocks.KubePodInterface).On("Update", pod1).Return(pod1, nil)
	kube.Pods("testns").(*mocks.KubePodInterface).On("Update", pod2).Return(pod2, nil)

	podStore.On("ListKeys").Return([]string{"testns/test-sv1", "testns/test-sv2"})
	podStore.On("GetByKey", "testns/test-sv1").Return(pod1, true, nil)
	podStore.On("GetByKey", "testns/test-sv2").Return(pod2, true, nil)
	serviceStore.On("List").Return([]interface{}{})

	shutdown := make(chan struct{})
	go controller.Run(shutdown)
	controller.AddPod(pod1)
	controller.AddPod(pod2)
	time.Sleep(100 * time.Millisecond)
	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}

	assert.True(t, checker.Check())

	vmi, err := types.VirtualMachineInterfaceByName(client, "default-domain:testns:test-sv1")
	assert.NoError(t, err)
	if err == nil {
		vmi.ClearVirtualMachine()
		err = client.Update(vmi)
		assert.NoError(t, err)
	}
	vm, err := types.VirtualMachineByName(client, "default-domain:testns:test-sv1")
	assert.NoError(t, err)
	if err == nil {
		err = client.Delete(vm)
		assert.NoError(t, err)
	}
	assert.False(t, checker.Check())
}
func TestConsistencyServiceIp(t *testing.T) {
	client := createTestClient()
	podStore := new(mocks.Store)
	serviceStore := new(mocks.Store)
	checker := NewConsistencyChecker(client, NewConfig(), podStore, serviceStore, nil)

	kube := mocks.NewKubeClient()
	controller := NewTestController(kube, client, nil, nil)
	config := controller.config

	netnsProject := new(types.Project)
	netnsProject.SetFQName("domain", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	installPods(controller, &kube.PodInterface.Mock, &podStore.Mock, "testns", 3)

	service1 := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s1",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "services",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"app": "pod01",
			},
			ClusterIP: "10.254.42.42",
			Type:      api.ServiceTypeLoadBalancer,
		},
	}
	service2 := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s2",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "services",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"app": "pod02",
			},
			ClusterIP:   "10.254.42.43",
			ExternalIPs: []string{"10.1.4.89"},
		},
	}
	service3 := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s3",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "services",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"app": "pod01",
			},
			ClusterIP: "10.254.42.44",
		},
	}

	kube.ServiceInterface.On("Update", service1).Return(service1, nil)

	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	controller.AddService(service1)
	controller.AddService(service2)
	controller.AddService(service3)
	serviceStore.On("List").Return([]interface{}{service1, service2, service3})
	time.Sleep(100 * time.Millisecond)

	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}
	time.Sleep(100 * time.Millisecond)

	assert.True(t, checker.Check())

	pool, err := types.FloatingIpPoolByName(client, "default-domain:testns:service-services:service-services")
	assert.NoError(t, err)
	vmi, err := types.VirtualMachineInterfaceByName(client, "default-domain:testns:pod01")
	assert.NoError(t, err)
	vip := new(types.FloatingIp)
	fqn := make([]string, len(pool.GetFQName())+1)
	copy(fqn, pool.GetFQName())
	fqn[len(pool.GetFQName())] = "s4"
	vip.SetFQName(vip.GetDefaultParentType(), fqn)
	vip.AddVirtualMachineInterface(vmi)
	assert.NoError(t, client.Create(vip))
	assert.False(t, checker.Check())

	assert.NoError(t, client.Delete(vip))
	assert.True(t, checker.Check())

	vip, err = types.FloatingIpByName(client, "default-domain:testns:service-services:service-services:s3")
	assert.NoError(t, err)
	assert.NoError(t, client.Delete(vip))

	assert.False(t, checker.Check())
}
func TestConsistencyPodUpdateRemovePrev(t *testing.T) {
	env := new(TestFramework)
	env.SetUp("192.0.2.0/24")
	client := env.client
	config := env.config

	pod1 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "x-1",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":                  "client",
				config.NetworkTag:       "client",
				config.NetworkAccessTag: "red",
			},
		},
	}

	pod2 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "x-2",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":                  "client",
				config.NetworkTag:       "client",
				config.NetworkAccessTag: "red",
			},
		},
	}

	pod3 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "redPod",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":            "red",
				config.NetworkTag: "redPrivate",
			},
		},
	}

	pod4 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "bluePod",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":            "blue",
				config.NetworkTag: "bluePrivate",
			},
		},
	}

	redService := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "red",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "red",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"Name": "red",
			},
			ClusterIP: "10.254.42.42",
		},
	}

	blueService := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "blue",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "blue",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"Name": "blue",
			},
			ClusterIP: "10.254.42.43",
		},
	}

	netnsProject := new(types.Project)
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	env.Start()

	env.AddPod(pod1)
	env.AddService(redService, "red")
	env.AddPod(pod2)
	env.AddPod(pod3)
	env.AddPod(pod4)
	env.AddService(blueService, "blue")
	env.SyncBarrier()

	serviceConnections := getNetworkServiceConnections(t, client, config, "testns", "client")
	assert.EqualValues(t, []string{"default", "red"}, serviceConnections)
	assert.True(t, env.checker.Check())
	policyName := makeServicePolicyName(config, "testns", "red")
	_, err := types.NetworkPolicyByName(client, strings.Join(policyName, ":"))
	assert.NoError(t, err)

	clonePodAndUpdateAccessTag := func(pod *api.Pod, color string) *api.Pod {
		newPod := new(api.Pod)
		*newPod = *pod
		newPod.Labels = make(map[string]string, 0)
		for k, v := range pod.Labels {
			newPod.Labels[k] = v
		}
		newPod.Labels[config.NetworkAccessTag] = color
		return newPod
	}

	// Update connections on pod1
	nPod1 := clonePodAndUpdateAccessTag(pod1, "blue")
	env.UpdatePod(pod1, nPod1)
	env.SyncBarrier()

	serviceConnections = getNetworkServiceConnections(t, client, config, "testns", "client")
	assert.EqualValues(t, []string{"default", "red", "blue"}, serviceConnections)
	assert.True(t, env.checker.Check(), "red and blue present")

	// Update connections on pod2
	// This will leave a stale connection to network red.
	nPod2 := clonePodAndUpdateAccessTag(pod2, "blue")
	env.UpdatePod(pod2, nPod2)
	env.SyncBarrier()

	serviceConnections = getNetworkServiceConnections(t, client, config, "testns", "client")
	assert.EqualValues(t, []string{"default", "red", "blue"}, serviceConnections)

	assert.False(t, env.checker.Check())

	env.DeleteService(redService, "red")
	env.SyncBarrier()

	// The second pass will delete the connection to network red.
	assert.False(t, env.checker.Check())
	serviceConnections = getNetworkServiceConnections(t, client, config, "testns", "client")
	assert.EqualValues(t, []string{"default", "blue"}, serviceConnections)

	assert.True(t, env.checker.Check())

	env.Shutdown()

	_, err = types.NetworkPolicyByName(client, strings.Join(policyName, ":"))
	assert.Error(t, err)
}
func TestConsistencyConnectionsDelete(t *testing.T) {
	env := new(TestFramework)
	env.SetUp("192.0.2.0/24")

	client := env.client
	config := env.config
	config.ClusterServices = []string{"kube-system/dns", "kube-system/monitoring"}

	// 2 client pods in network "private"
	pod1 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "pod01",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":                  "private",
				config.NetworkTag:       "private",
				config.NetworkAccessTag: "tagA",
			},
		},
	}

	pod2 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "pod02",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":                  "private",
				config.NetworkTag:       "private",
				config.NetworkAccessTag: "tagB",
			},
		},
	}

	// The service pods for service tagA and tagB respectivly.
	pod3 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "pod03",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":            "provider01",
				config.NetworkTag: "svc-backend",
				"app":             "provider01",
			},
		},
	}

	pod4 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "pod04",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"Name":            "provider02",
				config.NetworkTag: "svc-backend",
				"app":             "provider02",
			},
		},
	}

	// And the services
	service1 := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "service1",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "tagA",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"app": "provider01",
			},
			ClusterIP: "10.254.42.42",
			Type:      api.ServiceTypeClusterIP,
		},
	}

	service2 := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "service1",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "tagB",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"app": "provider02",
			},
			ClusterIP: "10.254.42.43",
			Type:      api.ServiceTypeClusterIP,
		},
	}

	netnsProject := new(types.Project)
	netnsProject.SetFQName("domain", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	sysProject := new(types.Project)
	sysProject.SetFQName("domain", []string{"default-domain", "kube-system"})
	client.Create(sysProject)

	env.Start()

	env.AddPod(pod1)
	env.AddPod(pod2)
	env.AddPod(pod3)
	env.AddPod(pod4)
	env.AddService(service1, "provider01")
	env.AddService(service2, "provider02")

	env.SyncBarrier()
	assert.True(t, env.checker.Check())

	env.DeletePod(pod2)
	env.SyncBarrier()

	assert.False(t, env.checker.Check())
	assert.False(t, env.checker.Check())
	assert.True(t, env.checker.Check())

	config.ClusterServices = []string{"kube-system/dns"}

	assert.False(t, env.checker.Check())
	assert.False(t, env.checker.Check())
	assert.True(t, env.checker.Check())

	env.Shutdown()
}
func TestConsistencyServiceIp(t *testing.T) {
	env := new(TestFramework)
	env.SetUp("192.0.2.0/24")
	config := env.config
	client := env.client

	netnsProject := new(types.Project)
	netnsProject.SetFQName("domain", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	service1 := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s1",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "services",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"Name": "pod01",
			},
			ClusterIP: "10.254.42.42",
			Type:      api.ServiceTypeLoadBalancer,
		},
	}
	service2 := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s2",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "services",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"Name": "pod02",
			},
			ClusterIP:   "10.254.42.43",
			ExternalIPs: []string{"10.1.4.89"},
		},
	}
	service3 := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s3",
			Namespace: "testns",
			Labels: map[string]string{
				config.NetworkTag: "services",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"Name": "pod01",
			},
			ClusterIP: "10.254.42.44",
		},
	}

	env.Start()

	installPods(env, "testns", 3)
	env.AddService(service1, "pod01")
	env.AddService(service2, "pod02")
	env.AddService(service3, "pod01")
	env.SyncBarrier()
	env.Shutdown()

	assert.True(t, env.checker.Check())

	pool, err := types.FloatingIpPoolByName(client, "default-domain:testns:service-services:service-services")
	assert.NoError(t, err)
	vmi, err := types.VirtualMachineInterfaceByName(client, "default-domain:testns:pod01")
	assert.NoError(t, err)
	vip := new(types.FloatingIp)
	fqn := make([]string, len(pool.GetFQName())+1)
	copy(fqn, pool.GetFQName())
	fqn[len(pool.GetFQName())] = "s4"
	vip.SetFQName(vip.GetDefaultParentType(), fqn)
	vip.AddVirtualMachineInterface(vmi)
	assert.NoError(t, client.Create(vip))
	assert.False(t, env.checker.Check())

	assert.NoError(t, client.Delete(vip))
	assert.True(t, env.checker.Check())

	vip, err = types.FloatingIpByName(client, "default-domain:testns:service-services:service-services:s3")
	assert.NoError(t, err)
	assert.NoError(t, client.Delete(vip))

	assert.False(t, env.checker.Check())
}
func TestPodDelete(t *testing.T) {
	client := new(contrail_mocks.ApiClient)
	client.Init()
	allocator := new(mocks.AddressAllocator)
	networkMgr := new(mocks.NetworkManager)
	controller := NewTestController(nil, client, allocator, networkMgr)

	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"name": "testnet",
			},
		},
	}

	netnsProject := new(types.Project)
	netnsProject.SetUuid(uuid.New())
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	assert.NoError(t, client.Create(netnsProject))

	instance := new(types.VirtualMachine)
	fqn := []string{"default-domain", "testns", "test"}
	instance.SetFQName("project", fqn)
	instance.SetUuid(string(pod.ObjectMeta.UID))
	assert.NoError(t, client.Create(instance))

	vmi := new(types.VirtualMachineInterface)
	vmi.SetFQName("project", fqn)
	vmi.AddVirtualMachine(instance)
	assert.NoError(t, client.Create(vmi))

	ipObj := new(types.InstanceIp)
	ipObj.SetName("testns_test")
	assert.NoError(t, client.Create(ipObj))

	allocator.On("ReleaseIpAddress", string(pod.ObjectMeta.UID)).Return()
	networkMgr.On("ReleaseNetworkIfEmpty", "testns", "testnet").Return(true, nil)

	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	controller.DeletePod(pod)

	time.Sleep(100 * time.Millisecond)
	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}

	if obj, err := client.FindByName("virtual-machine", strings.Join(fqn, ":")); err == nil {
		t.Errorf("virtual-machine object still present %s", obj.GetUuid())
	}
	if obj, err := client.FindByUuid("virtual-machine-interface", vmi.GetUuid()); err == nil {
		t.Errorf("virtual-machine-interface object still present %s", obj.GetUuid())
	}
	if obj, err := client.FindByUuid("instance-ip", ipObj.GetUuid()); err == nil {
		t.Errorf("instance-ip object still present %s", obj.GetUuid())
	}

	allocator.AssertExpectations(t)
}
func TestServiceWithMultipleUsers(t *testing.T) {
	kube := mocks.NewKubeClient()

	client := new(contrail_mocks.ApiClient)
	client.Init()

	client.AddInterceptor("virtual-machine-interface", &VmiInterceptor{})
	client.AddInterceptor("virtual-network", &NetworkInterceptor{})

	allocator := new(mocks.AddressAllocator)

	controller := NewTestController(kube, client, allocator, nil)

	pod1 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-server",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"name": "server",
			},
		},
	}
	pod2 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-xz1",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"name": "client1",
				"uses": "x1",
			},
		},
	}
	pod3 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-xz2",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"name": "client1",
				"uses": "x1",
			},
		},
	}
	pod4 := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      "test-xz3",
			Namespace: "testns",
			UID:       kubetypes.UID(uuid.New()),
			Labels: map[string]string{
				"name": "client2",
				"uses": "x1",
			},
		},
	}
	service := &api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:      "s1",
			Namespace: "testns",
			Labels: map[string]string{
				"name": "x1",
			},
		},
		Spec: api.ServiceSpec{
			Selector: map[string]string{
				"name": "server",
			},
			ClusterIP: "10.254.42.42",
		},
	}

	netnsProject := new(types.Project)
	netnsProject.SetFQName("", []string{"default-domain", "testns"})
	client.Create(netnsProject)

	allocator.On("LocateIpAddress", string(pod1.ObjectMeta.UID)).Return("10.0.0.1", nil)
	allocator.On("LocateIpAddress", string(pod2.ObjectMeta.UID)).Return("10.0.0.2", nil)
	allocator.On("LocateIpAddress", string(pod3.ObjectMeta.UID)).Return("10.0.0.3", nil)
	allocator.On("LocateIpAddress", string(pod4.ObjectMeta.UID)).Return("10.0.0.4", nil)
	allocator.On("ReleaseIpAddress", string(pod1.ObjectMeta.UID)).Return()
	allocator.On("ReleaseIpAddress", string(pod2.ObjectMeta.UID)).Return()
	allocator.On("ReleaseIpAddress", string(pod3.ObjectMeta.UID)).Return()
	allocator.On("ReleaseIpAddress", string(pod4.ObjectMeta.UID)).Return()

	kube.PodInterface.On("Update", pod1).Return(pod1, nil)
	kube.PodInterface.On("Update", pod2).Return(pod2, nil)
	kube.PodInterface.On("Update", pod3).Return(pod3, nil)
	kube.PodInterface.On("Update", pod4).Return(pod4, nil)
	kube.PodInterface.On("List", mock.Anything, mock.Anything).Return(&api.PodList{Items: []api.Pod{*pod1}}, nil)

	shutdown := make(chan struct{})
	go controller.Run(shutdown)

	controller.AddPod(pod1)
	controller.AddService(service)
	controller.AddPod(pod2)
	controller.AddPod(pod3)
	controller.AddPod(pod4)

	time.Sleep(100 * time.Millisecond)

	policy, err := types.NetworkPolicyByName(client, "default-domain:testns:x1")
	assert.NoError(t, err)
	if err == nil {
		assert.Len(t, policy.GetNetworkPolicyEntries().PolicyRule, 2)
		assert.True(t, policyHasRule(policy, "default-domain:testns:client1", "default-domain:testns:service-x1"))
		assert.True(t, policyHasRule(policy, "default-domain:testns:client2", "default-domain:testns:service-x1"))
	}

	_, err = types.VirtualNetworkByName(client, "default-domain:testns:client2")
	assert.NoError(t, err)

	controller.DeletePod(pod3)
	time.Sleep(100 * time.Millisecond)

	policy, err = types.NetworkPolicyByName(client, "default-domain:testns:x1")
	assert.NoError(t, err)
	if err == nil {
		assert.Len(t, policy.GetNetworkPolicyEntries().PolicyRule, 2)
	}

	controller.DeletePod(pod4)
	time.Sleep(100 * time.Millisecond)

	_, err = types.VirtualNetworkByName(client, "default-domain:testns:client2")
	assert.Error(t, err)

	policy, err = types.NetworkPolicyByName(client, "default-domain:testns:x1")
	assert.NoError(t, err)
	if err == nil {
		assert.Len(t, policy.GetNetworkPolicyEntries().PolicyRule, 1)
		assert.True(t, policyHasRule(policy, "default-domain:testns:client1", "default-domain:testns:service-x1"))
	}

	controller.DeletePod(pod2)
	time.Sleep(100 * time.Millisecond)

	policy, err = types.NetworkPolicyByName(client, "default-domain:testns:x1")
	assert.NoError(t, err)
	if err == nil {
		assert.Len(t, policy.GetNetworkPolicyEntries().PolicyRule, 0)
	}

	controller.DeletePod(pod1)
	controller.DeleteService(service)
	time.Sleep(100 * time.Millisecond)

	type shutdownMsg struct {
	}
	shutdown <- shutdownMsg{}

	policy, err = types.NetworkPolicyByName(client, "default-domain:testns:x1")
	assert.Error(t, err)
}