def test_missing(self):
        depl = resource.VmmInjectedDeployment(
            **{
                'display_name': '',
                'name': 'kubedns',
                'replicas': 1,
                'domain_name': 'kube',
                'controller_name': 'kube',
                'domain_type': 'Kubernetes',
                'guid': 'a',
                'namespace_name': 'k'
            })
        ns = resource.VmmInjectedNamespace(
            **{
                'display_name': '',
                'name': 'k',
                'domain_name': 'kube',
                'controller_name': 'kube',
                'domain_type': 'Kubernetes'
            })
        updates = [depl, ns, ns]

        mgr = aim_manager.AimManager()

        tt_maker = tree_manager.AimHashTreeMaker()
        tt_builder = tree_manager.HashTreeBuilder(mgr)
        trees = {}

        exp_key = tt_maker._build_hash_tree_key(depl)

        for aim_res in updates:
            key = tt_maker.get_root_key(aim_res)
            if key and trees is not None:
                cfg = trees.setdefault(tt_builder.CONFIG, {}).setdefault(
                    key, tree.StructuredHashTree())
                mo = trees.setdefault(tt_builder.MONITOR,
                                      {}).setdefault(key,
                                                     tree.StructuredHashTree())
                oper = trees.setdefault(tt_builder.OPER, {}).setdefault(
                    key, tree.StructuredHashTree())

                tt_builder.build(
                    [aim_res], [], [], {
                        tt_builder.CONFIG: {
                            key: cfg
                        },
                        tt_builder.MONITOR: {
                            key: mo
                        },
                        tt_builder.OPER: {
                            key: oper
                        }
                    },
                    aim_ctx=self.ctx)

            if not isinstance(aim_res, resource.VmmInjectedDeployment):
                self.assertIsNotNone(cfg.find(exp_key),
                                     'Resource %s' % aim_res)
                self.assertIsNotNone(trees['config']['comp'].find(exp_key),
                                     'Resource %s' % aim_res)
    def test_process_pod_status_event(self):
        watcher = k8s_watcher.K8sWatcher()
        store = self.ctx.store

        ns = resource.VmmInjectedNamespace(domain_type='Kubernetes',
                                           domain_name='kubernetes',
                                           controller_name='kube-cluster',
                                           name='ns-%s' % self.test_id)
        pod = resource.VmmInjectedContGroup(domain_type=ns.domain_type,
                                            domain_name=ns.domain_name,
                                            controller_name=ns.controller_name,
                                            namespace_name=ns.name,
                                            name='pod1')
        pod_ht_key = watcher.tt_builder.tt_maker._build_hash_tree_key(pod)

        self.mgr.create(self.ctx, ns)

        pod_db_obj = store.make_db_obj(pod)
        store.add(pod_db_obj)
        pod_db_obj = store.query(api_v1.Pod,
                                 resource.VmmInjectedContGroup,
                                 namespace_name=ns.name,
                                 name=pod.name)[0]

        pod.name = 'hidden-pod1'
        hidden_pod_ht_key = (
            watcher.tt_builder.tt_maker._build_hash_tree_key(pod))
        hidden_pod_db_obj = store.make_db_obj(pod)
        hidden_pod_db_obj['spec']['hostNetwork'] = True
        store.add(hidden_pod_db_obj)
        hidden_pod_db_obj = store.query(api_v1.Pod,
                                        resource.VmmInjectedContGroup,
                                        namespace_name=ns.name,
                                        name=pod.name)[0]

        # test pod that is not hidden
        stat = status.AciStatus(resource_type='VmmInjectedContGroup',
                                resource_id=pod_db_obj.aim_id,
                                resource_root=pod.root)
        for t in ['ADDED', 'MODIFIED', 'DELETED']:
            ev = {'event_type': t, 'resource': stat}
            exp_ev = copy.copy(ev)

            watcher._process_pod_status_event(ev)
            self.assertEqual(exp_ev, ev)

        # seed the hash-tree with the non-hidden pod
        ev = {'type': 'ADDED', 'object': pod_db_obj}
        watcher._process_event(ev)
        cfg_tree = watcher.trees['config'][pod.root]
        self.assertIsNotNone(cfg_tree.find(pod_ht_key))

        # test pod that is hidden
        stat.resource_id = hidden_pod_db_obj.aim_id
        for t in ['ADDED', 'MODIFIED', 'DELETED']:
            ev = {'event_type': t, 'resource': stat}
            exp_ev = copy.copy(ev)
            exp_ev['event_type'] = 'DELETED'
            watcher._process_pod_status_event(ev)
            self.assertEqual(exp_ev, ev)

            ev2 = {'type': t, 'object': store.make_db_obj(stat)}
            watcher._process_event(ev2)
            self.assertIsNone(cfg_tree.find(hidden_pod_ht_key))
    def test_endpoints_event(self):
        watcher = k8s_watcher.K8sWatcher()
        store = self.ctx.store

        ns = resource.VmmInjectedNamespace(domain_type='Kubernetes',
                                           domain_name='kubernetes',
                                           controller_name='kube-cluster',
                                           name='ns-%s' % self.test_id)
        svc = resource.VmmInjectedService(domain_type=ns.domain_type,
                                          domain_name=ns.domain_name,
                                          controller_name=ns.controller_name,
                                          namespace_name=ns.name,
                                          name='svc1',
                                          service_ports=[{
                                              'port': '23',
                                              'protocol': 'tcp',
                                              'target_port': '45'
                                          }],
                                          endpoints=[{
                                              'ip': '1.2.3.4',
                                              'pod_name': 'foo'
                                          }, {
                                              'ip': '2.1.3.4',
                                              'pod_name': 'bar'
                                          }])

        svc_db_obj = store.make_db_obj(svc)
        ep_db_obj = svc_db_obj.endpoints
        ep_db_obj['subsets'][0]['ports'] = [{'port': 80}]

        ev_obj = {'kind': ep_db_obj.kind, 'apiVersion': ep_db_obj.api_version}
        ev_obj.update(ep_db_obj)
        ev = {'type': 'ADDED', 'object': ev_obj}

        # event with no Service object
        self.assertIsNone(watcher._parse_event(ev))

        def _verify_event_processing(exp_svc):
            res = watcher._parse_event(ev)
            self.assertEqual('modified', res['event_type'])
            self.assertEqual(resource.VmmInjectedService,
                             type(res['resource']))
            for attr in ['name', 'namespace_name', 'endpoints']:
                self.assertEqual(getattr(exp_svc, attr),
                                 getattr(res['resource'], attr))

            aff_ten = watcher._process_event(ev)
            self.assertEqual(set(['vmmp-Kubernetes']), aff_ten)
            cfg_tree = watcher.trees['config']['vmmp-Kubernetes']
            ht_key = (
                watcher.tt_builder.tt_maker._build_hash_tree_key(exp_svc))
            ht_children = [
                x.key for x in cfg_tree.find(ht_key).get_children()
                if 'vmmInjectedSvcEp|' in x.key[-1]
            ]
            self.assertEqual(len(exp_svc.endpoints), len(ht_children))
            for e in exp_svc.endpoints:
                child_key = ht_key + ('vmmInjectedSvcEp|%s' % e['pod_name'], )
                self.assertTrue(child_key in ht_children, child_key)

        # create Service and Endpoints, send event
        self.mgr.create(self.ctx, ns)
        self.mgr.create(self.ctx, svc)
        store.klient.create(type(ep_db_obj),
                            ep_db_obj['metadata']['namespace'], ep_db_obj)
        _verify_event_processing(svc)

        # update Endpoints, send event
        ep_db_obj['subsets'][0]['addresses'] = (
            ep_db_obj['subsets'][0]['addresses'][:-1])
        store.klient.replace(type(ep_db_obj), ep_db_obj['metadata']['name'],
                             ep_db_obj['metadata']['namespace'], ep_db_obj)
        svc.endpoints = svc.endpoints[:-1]
        ev['type'] = 'MODIFIED'
        _verify_event_processing(svc)

        # delete Endpoints, send event
        store.klient.delete(type(ep_db_obj), ep_db_obj['metadata']['name'],
                            ep_db_obj['metadata']['namespace'], {})
        ev['type'] = 'DELETED'
        svc.endpoints = []
        _verify_event_processing(svc)