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