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 (m *NetworkManagerImpl) disconnectNetworkFromPolicy(policy *types.NetworkPolicy, targetCSN string) error {
	target, err := types.VirtualNetworkByName(m.client, targetCSN)
	if err != nil {
		return err
	}
	err = target.DeleteNetworkPolicy(policy.GetUuid())
	if err != nil {
		return err
	}
	return m.client.Update(target)
}
// global networks can be created externally. Attached the network to the respective policy in case
// the policy was created first.
func (c *consistencyChecker) globalNetworkChecker() bool {
	success := true
	for _, gbl := range c.config.GlobalNetworks {
		network, err := types.VirtualNetworkByName(c.client, gbl)
		if err != nil {
			glog.V(5).Infof("Network %s: %v", gbl, err)
			continue
		}
		if !c.globalNetworkCheckPolicyAttachment(network) {
			success = false
		}
	}
	return success
}
func getNetworkServiceConnections(t *testing.T, client contrail.ApiClient, config *Config, namespace, networkName string) []string {
	network, err := types.VirtualNetworkByName(client, strings.Join([]string{config.DefaultDomain, namespace, networkName}, ":"))
	require.NoError(t, err)
	policyRefs, err := network.GetNetworkPolicyRefs()
	require.NoError(t, err)
	serviceList := make([]string, 0, len(policyRefs))
	for _, ref := range policyRefs {
		svc, err := serviceNameFromPolicyName(ref.To[2])
		if err != nil {
			continue
		}
		serviceList = append(serviceList, svc)
	}
	return serviceList
}
// Connect creates a network-policy and corresponding policy rule (when they do not exist) in order to
// connect the source network with the target. The target network may or not exist yet.
func (m *NetworkManagerImpl) Connect(network *types.VirtualNetwork, targetCSN string) error {
	targetName := strings.Split(targetCSN, ":")
	policy, err := m.locatePolicy(targetName)
	if err != nil {
		return err
	}

	policyAttach(m.client, network, policy)

	target, err := types.VirtualNetworkByName(m.client, targetCSN)
	if err == nil {
		err = policyAttach(m.client, target, policy)
		if err != nil {
			glog.Error(err)
		}
	}

	err = policyLocateRuleByFQN(m.client, policy, network.GetFQName(), targetName)
	if err != nil {
		return err
	}
	return nil
}
func (c *consistencyChecker) NetworkChecker(connections networkConnectionMap) bool {
	lastPolicyMap := c.gcPolicyMap
	c.gcPolicyMap = make(networkConnectionMap, 0)

	var kubeNetworks sort.StringSlice
	connectionCheck := true

	for k, v := range connections {
		kubeNetworks = append(kubeNetworks, k)
		if c.serviceMgr == nil {
			continue
		}
		network, err := types.VirtualNetworkByName(c.client, k)
		if err != nil {
			glog.Error(err)
			continue
		}

		// State policy references are removed if they are found to be stale in
		// two successive cycles.
		c.serviceMgr.PurgeStalePolicyRefs(network, v,
			func(namespace, service string) bool {
				networkName := strings.Join(network.GetFQName(), ":")
				if entry, ok := lastPolicyMap[networkName]; ok {
					if entry.Contains(namespace, service) {
						glog.Infof("%s service connection %s/%s delete", networkName, namespace, service)
						connectionCheck = false
						return true
					}
				}
				var serviceList ServiceIdList
				if entry, ok := c.gcPolicyMap[networkName]; ok {
					serviceList = entry
				} else {
					serviceList = MakeServiceIdList()
				}
				glog.Infof("%s service connection %s/%s not used by pod specifications",
					networkName, namespace, service)
				serviceList.Add(namespace, service)
				c.gcPolicyMap[networkName] = serviceList
				connectionCheck = false
				return false
			})
	}

	// consider service networks.
	c.addServiceNetworks(&kubeNetworks)

	kubeNetworks.Sort()

	var dbNetworks sort.StringSlice
	elements, err := c.client.List("virtual-network")
	if err != nil {
		glog.Error(err)
		return false
	}
	for _, ref := range elements {
		networkName := strings.Join(ref.Fq_name, ":")
		if networkName == c.config.PublicNetwork {
			continue
		}
		if isSystemDefaultNetwork(networkName) {
			continue
		}
		dbNetworks = append(dbNetworks, networkName)
	}
	dbNetworks.Sort()

	cmp := CompareSortedLists(kubeNetworks, dbNetworks,
		func(key string) {
			glog.Errorf("network %s not present in opencontrail db", key)
		},
		func(key string) {
			glog.Errorf("network %s not used by kubernetes", key)
			if c.serviceMgr == nil {
				return
			}
			network, err := types.VirtualNetworkByName(c.client, key)
			if err != nil {
				glog.Error(err)
				return
			}
			c.serviceMgr.PurgeStalePolicyRefs(network, MakeServiceIdList(), func(string, string) bool { return true })
		},
		func(key string) bool {
			return true
		})
	return connectionCheck && cmp
}
func (c *consistencyChecker) NetworkChecker(connections networkServiceMap) bool {
	lastPolicyMap := c.staleConnectionMap
	c.staleConnectionMap = make(networkConnectionMap, 0)

	var kubeNetworks sort.StringSlice
	connectionCheck := true

	for k, v := range connections {
		kubeNetworks = append(kubeNetworks, k)
		if c.serviceMgr == nil {
			continue
		}
		network, err := types.VirtualNetworkByName(c.client, k)
		if err != nil {
			glog.Error(err)
			continue
		}

		status, err := c.networkEvalPolicyRefs(network, v, lastPolicyMap)
		if err != nil {
			glog.Error(err)
			continue
		}
		if !status {
			connectionCheck = false
		}
	}

	// consider service networks.
	c.addServiceNetworks(&kubeNetworks)

	kubeNetworks.Sort()

	var dbNetworks sort.StringSlice
	elements, err := c.client.List("virtual-network")
	if err != nil {
		glog.Error(err)
		return false
	}
	for _, ref := range elements {
		networkName := strings.Join(ref.Fq_name, ":")
		if networkName == c.config.PublicNetwork {
			continue
		}
		if isSystemDefaultNetwork(networkName) {
			continue
		}
		dbNetworks = append(dbNetworks, networkName)
	}
	dbNetworks.Sort()

	cmp := CompareSortedLists(kubeNetworks, dbNetworks,
		func(key string) {
			glog.Errorf("network %s not present in opencontrail db", key)
		},
		func(key string) {
			glog.Errorf("network %s not used by kubernetes", key)
			if c.serviceMgr == nil {
				return
			}
			network, err := types.VirtualNetworkByName(c.client, key)
			if err != nil {
				glog.Error(err)
				return
			}
			c.networkEvalPolicyRefs(network, MakeServiceIdList(), nil)
		},
		func(key string) bool {
			return true
		})
	return connectionCheck && cmp
}
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)
}