From 028ea7aa9ec7baf71bc0014e448e5959c80eb095 Mon Sep 17 00:00:00 2001
From: Erik Reid <erik.reid@geant.org>
Date: Thu, 7 Feb 2019 15:08:30 +0100
Subject: [PATCH] added /data/reload-router-config

---
 inventory_provider/routes/jobs.py     |   6 ++
 test/conftest.py                      |  27 ++++++
 test/per_router/test_celery_worker.py | 124 ++++++++++++++++++++------
 test/per_router/test_juniper_data.py  |  23 -----
 4 files changed, 131 insertions(+), 49 deletions(-)

diff --git a/inventory_provider/routes/jobs.py b/inventory_provider/routes/jobs.py
index 5de2023c..81e6501f 100644
--- a/inventory_provider/routes/jobs.py
+++ b/inventory_provider/routes/jobs.py
@@ -15,3 +15,9 @@ def update():
 def update_interface_statuses():
     worker.update_interface_statuses().async_start()
     return Response("OK")
+
+
+@routes.route("reload-router-config/<equipment_name>")
+def reload_router_config(equipment_name):
+    worker.reload_router_config().async_start(equipment_name)
+    return Response("OK")
diff --git a/test/conftest.py b/test/conftest.py
index 304333c6..ca700022 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -1,4 +1,6 @@
+import ast
 import json
+import netifaces
 import os
 import re
 import shutil
@@ -165,3 +167,28 @@ def mocked_redis(mocker):
     mocker.patch(
         'inventory_provider.routes.common.redis.StrictRedis',
         MockedRedis)
+
+
+NETIFACES_TEST_DATA_STRING = """{
+    'lo0':  {{AF_INET}: [{'addr': '127.0.0.1', 'netmask': '255.0.0.0', 'peer': '127.0.0.1'}],
+             {AF_INET6}: [{'addr': '::1', 'netmask': 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128', 'peer': '::1', 'flags': 0},
+                 {'addr': 'fe80::1%lo0', 'netmask': 'ffff:ffff:ffff:ffff::/64', 'flags': 0}]},
+    'eth0': {{AF_LINK}: [{'addr': '78:4f:43:76:73:ba'}],
+             {AF_INET}: [{'addr': '83.97.92.239', 'netmask': '255.255.252.0', 'broadcast': '83.97.95.255'}],
+             {AF_INET6}: [{'addr': 'fe80::250:56ff:fea1:8340', 'netmask': 'ffff:ffff:ffff:ffff::/64', 'flags': 1024},
+                 {'addr': '2001:798:3::104', 'netmask': 'ffff:ffff:ffff:ffff::/64', 'flags': 1088}]}
+}"""  # noqa E501
+
+
+@pytest.fixture
+def mocked_netifaces(mocker):
+    s = NETIFACES_TEST_DATA_STRING
+    for k, v in {
+                'AF_INET': netifaces.AF_INET,
+                'AF_INET6': netifaces.AF_INET6,
+                'AF_LINK': netifaces.AF_LINK
+            }.items():
+        s = s.replace('{%s}' % k, str(v))
+    data = ast.literal_eval(s)
+    mocker.patch('netifaces.interfaces', lambda: data.keys())
+    mocker.patch('netifaces.ifaddresses', lambda n: data[n])
diff --git a/test/per_router/test_celery_worker.py b/test/per_router/test_celery_worker.py
index 49c53ba7..5e42de20 100644
--- a/test/per_router/test_celery_worker.py
+++ b/test/per_router/test_celery_worker.py
@@ -4,67 +4,139 @@ and some data ends up in the right place ... otherwise not very detailed
 """
 import json
 import logging
+import os
+import re
 
 from lxml import etree
 import pytest
 from inventory_provider.tasks import worker
 
+import inventory_provider
+
+TEST_DATA_DIRNAME = os.path.realpath(os.path.join(
+    inventory_provider.__path__[0],
+    '..',
+    'test',
+    'data'))
+
+# class MockedRedis(object):
+#
+#     db = {}
+#
+#     def __init__(self, *args, **kwargs):
+#         pass
+#
+#     def set(self, name, value):
+#         assert isinstance(value, str)
+#         if name.startswith('netconf:'):
+#             etree.fromstring(value)
+#         elif name.startswith('snmp-interfaces:'):
+#             obj = json.loads(value)
+#             assert isinstance(obj, list)
+#         MockedRedis.db[name] = value
+#
+#     def get(self, key):
+#         return MockedRedis.db[key].encode('utf-8')
 
 class MockedRedis(object):
 
-    db = {}
+    db = None
 
     def __init__(self, *args, **kwargs):
-        pass
+        if MockedRedis.db is None:
+            test_data_filename = os.path.join(
+                TEST_DATA_DIRNAME,
+                "router-info.json")
+            with open(test_data_filename) as f:
+                MockedRedis.db = json.loads(f.read())
 
     def set(self, name, value):
-        assert isinstance(value, str)
-        if name.startswith('netconf:'):
-            etree.fromstring(value)
-        elif name.startswith('snmp-interfaces:'):
-            obj = json.loads(value)
-            assert isinstance(obj, list)
         MockedRedis.db[name] = value
 
+    def get(self, name):
+        value = MockedRedis.db.get(name, None)
+        if value is None:
+            return None
+        return value.encode('utf-8')
+
+    def keys(self, glob=None):
+        if not glob:
+            return list([k.encode("utf-8") for k in MockedRedis.db.keys()])
+        m = re.match(r'^([^*]+)\*$', glob)
+        assert m  # all expected global are like this
+        return list([
+            k.encode("utf-8") for k in MockedRedis.db.keys()
+            if k.startswith(m.group(1))])
+
+    def delete(self, key):
+        if isinstance(key, bytes):
+            key = key.decode('utf-8')
+        del MockedRedis.db[key]
+
 
 @pytest.fixture
-def mocked_worker_module(mocker, data_config):
+def mocked_worker_module(mocker, data_config, cached_test_data, mocked_netifaces):
 
     worker.InventoryTask.config = data_config
-    worker.InventoryTask.logger = logging.getLogger()
-
-    MockedRedis.db = {}
 
     mocker.patch(
         'inventory_provider.tasks.common.redis.StrictRedis',
         MockedRedis)
 
-
-def test_netconf_refresh_config(
-        mocked_worker_module, mocker, router, cached_test_data):
+    def _mocked_snmp_interfaces(hostname, community, _):
+        return json.loads(cached_test_data['snmp-interfaces:' + hostname])
+    mocker.patch(
+        'inventory_provider.snmp.get_router_interfaces',
+        _mocked_snmp_interfaces)
 
     def _mocked_load_juniper_netconf_config(hostname, _):
         return etree.XML(cached_test_data['netconf:' + hostname])
-
     mocker.patch(
-        'inventory_provider.tasks.worker.juniper.load_config',
+        'inventory_provider.juniper.load_config',
         _mocked_load_juniper_netconf_config)
 
+
+def test_netconf_refresh_config(mocked_worker_module, router):
     assert 'netconf:' + router not in MockedRedis.db
     worker.netconf_refresh_config(router)
     assert MockedRedis.db['netconf:' + router]
 
 
-def test_snmp_refresh_interfaces(
-        mocked_worker_module, mocker, router, cached_test_data):
+def test_snmp_refresh_interfaces(mocked_worker_module, router):
+    assert 'snmp-interfaces:' + router not in MockedRedis.db
+    worker.snmp_refresh_interfaces(router, 'fake-community')
+    assert MockedRedis.db['snmp-interfaces:' + router]
 
-    def _mocked_snmp_interfaces(hostname, community, _):
-        return json.loads(cached_test_data['snmp-interfaces:' + hostname])
 
-    mocker.patch(
-        'inventory_provider.tasks.worker.snmp.get_router_interfaces',
-        _mocked_snmp_interfaces)
+def test_reload_router_config(mocked_worker_module, router, mocker):
+    unused = MockedRedis()  # init so that db is initialized
 
+    saved_data = {}
+    for key in ('netconf:' + router, 'snmp-interfaces:' + router):
+        saved_data[key] = MockedRedis.db.pop(key)
+    assert 'netconf:' + router not in MockedRedis.db
     assert 'snmp-interfaces:' + router not in MockedRedis.db
-    worker.snmp_refresh_interfaces(router, 'fake-community')
-    assert MockedRedis.db['snmp-interfaces:' + router]
+
+    def _mocked_netconf_refresh_config_apply(hostname):
+        key = 'netconf:' + hostname
+        MockedRedis.db[key] = saved_data[key]
+    mocker.patch(
+        'inventory_provider.tasks.worker.netconf_refresh_config.apply',
+        _mocked_netconf_refresh_config_apply)
+
+    def _mocked_snmp_refresh_interfaces_apply(args):
+        assert len(args) == 2
+        key = 'snmp-interfaces:' + args[0]
+        MockedRedis.db[key] = saved_data[key]
+    mocker.patch(
+        'inventory_provider.tasks.worker.snmp_refresh_interfaces.apply',
+        _mocked_snmp_refresh_interfaces_apply)
+
+    mocker.patch(
+        'inventory_provider.tasks.worker.snmp_refresh_interfaces.apply',
+        _mocked_snmp_refresh_interfaces_apply)
+
+    worker.reload_router_config(router)
+    assert 'netconf:' + router in MockedRedis.db
+    assert 'snmp-interfaces:' + router in MockedRedis.db
+
diff --git a/test/per_router/test_juniper_data.py b/test/per_router/test_juniper_data.py
index c40f025c..78f624b4 100644
--- a/test/per_router/test_juniper_data.py
+++ b/test/per_router/test_juniper_data.py
@@ -102,29 +102,6 @@ def test_bgp_list(netconf_doc):
     jsonschema.validate(routes, schema)
 
 
-NETIFACES_TEST_DATA_STRING = """{
-    'lo0':  {{AF_INET}: [{'addr': '127.0.0.1', 'netmask': '255.0.0.0', 'peer': '127.0.0.1'}],
-             {AF_INET6}: [{'addr': '::1', 'netmask': 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128', 'peer': '::1', 'flags': 0},
-                 {'addr': 'fe80::1%lo0', 'netmask': 'ffff:ffff:ffff:ffff::/64', 'flags': 0}]},
-    'eth0': {{AF_LINK}: [{'addr': '78:4f:43:76:73:ba'}],
-             {AF_INET}: [{'addr': '83.97.92.239', 'netmask': '255.255.252.0', 'broadcast': '83.97.95.255'}],
-             {AF_INET6}: [{'addr': 'fe80::250:56ff:fea1:8340', 'netmask': 'ffff:ffff:ffff:ffff::/64', 'flags': 1024},
-                 {'addr': '2001:798:3::104', 'netmask': 'ffff:ffff:ffff:ffff::/64', 'flags': 1088}]}
-}"""  # noqa E501
-
-
-@pytest.fixture
-def mocked_netifaces(mocker):
-    s = NETIFACES_TEST_DATA_STRING
-    for k, v in {
-                'AF_INET': netifaces.AF_INET,
-                'AF_INET6': netifaces.AF_INET6,
-                'AF_LINK': netifaces.AF_LINK
-            }.items():
-        s = s.replace('{%s}' % k, str(v))
-    data = ast.literal_eval(s)
-    mocker.patch('netifaces.interfaces', lambda: data.keys())
-    mocker.patch('netifaces.ifaddresses', lambda n: data[n])
 
 
 def test_snmp_community_string(mocked_netifaces, netconf_doc):
-- 
GitLab