""" tests of a few worker utilities """ import ipaddress import json import re import jsonschema from inventory_provider.tasks import worker from inventory_provider.tasks import common from inventory_provider.routes import msr def backend_db(): return common._get_redis({ 'redis': { 'hostname': None, 'port': None }, 'redis-databases': [0, 7] }).db def test_build_subnet_db(mocked_worker_module): """ Verify that valid reverse subnet objects are created. :param mocked_worker_module: fixture """ address_schema = { '$schema': 'http://json-schema.org/draft-07/schema#', 'definitions': { 'interface': { 'type': 'object', 'properties': { 'name': {'type': 'string'}, 'interface address': {'type': 'string'}, 'interface name': {'type': 'string'}, 'router': {'type': 'string'} }, 'required': ['name', 'interface address', 'interface name', 'router'], 'additionalProperties': False } }, 'type': 'array', 'items': {"$ref": "#/definitions/interface"}, } db = backend_db() # also forces initialization def _x(k): return k.startswith('subnets:') for k in list(filter(_x, db.keys())): del db[k] worker._build_subnet_db() found_record = False for key, value in db.items(): if not _x(key): continue found_record = True m = re.match('^subnets:(.+)', key) assert m address = m.group(1) value = json.loads(value) jsonschema.validate(value, address_schema) for ifc in value: assert ifc['interface address'] == address assert found_record def test_build_juniper_peering_db(mocked_worker_module): """ Verify that valid juniper peering db objects are created. :param mocked_worker_module: fixture """ # same as inventory_provider.juniper.PEERING_LIST_SCHEMA, # but with "hostname" in every returned record LOGICAL_SYSTEM_PEERING_SCHEMA = { "type": "object", "properties": { "logical-system": {"type": "string"}, "group": {"type": "string"}, "description": {"type": "string"}, "address": {"type": "string"}, "remote-asn": {"type": "integer"}, "local-asn": {"type": "integer"}, "hostname": {"type": "string"} }, # local/remote-asn and/or description are not always present, # just based on empirical tests - not a problem "required": ["logical-system", "group", "address"], "additionalProperties": False } TOP_LEVEL_PEERING_SCHEMA = { "type": "object", "properties": { "group": {"type": "string"}, "description": {"type": "string"}, "address": {"type": "string"}, "remote-asn": {"type": "integer"}, "local-asn": {"type": "integer"}, "hostname": {"type": "string"} }, # lots of internal peerings - so maybe no explicit asn's "required": ["group", "address"], "additionalProperties": False } INSTANCE_PEERING = { "type": "object", "properties": { "instance": {"type": "string"}, "group": {"type": "string"}, "description": {"type": "string"}, "address": {"type": "string"}, "remote-asn": {"type": "integer"}, "local-asn": {"type": "integer"}, "hostname": {"type": "string"} }, # description and-or local-asn is not always present, # just based on empirical tests - not a problem "required": ["instance", "group", "address", "remote-asn"], "additionalProperties": False } DETAILED_PEERING_LIST_SCHEMA = { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "top-level-peering": TOP_LEVEL_PEERING_SCHEMA, "instance-peering": INSTANCE_PEERING, "logical-system-peering": LOGICAL_SYSTEM_PEERING_SCHEMA, "peering": { "oneOf": [ {"$ref": "#/definitions/top-level-peering"}, {"$ref": "#/definitions/instance-peering"}, {"$ref": "#/definitions/logical-system-peering"} ] } }, "type": "array", "items": {"$ref": "#/definitions/peering"} } db = backend_db() # also forces initialization # remove the juniper-peerings:* items that # will be created by _build_juniper_peering_db def _x(k): if not k.startswith('juniper-peerings'): return False if k.startswith('juniper-peerings:hosts:'): return False return True for k in list(filter(_x, db.keys())): del db[k] worker._build_juniper_peering_db() found_record = False found_logical_system = False found_group = False for key, value in db.items(): if not _x(key): continue value = json.loads(value) assert value found_record = True if key.startswith('juniper-peerings:ix-groups:'): for address in value: canonical = ipaddress.ip_interface(address).ip.exploded assert address == canonical continue jsonschema.validate(value, DETAILED_PEERING_LIST_SCHEMA) if 'logical-system:' in key: jsonschema.validate(value, msr.PEERING_LIST_SCHEMA) m = re.match(r'.*logical-system:(.+)$', key) assert all(p['logical-system'] == m.group(1) for p in value) found_logical_system = True if 'group:' in key: jsonschema.validate(value, msr.PEERING_LIST_SCHEMA) m = re.match(r'.*group:(.+)$', key) assert all(p['group'] == m.group(1) for p in value) found_group = True assert found_record assert found_logical_system assert found_group def test_build_snmp_peering_db(mocked_worker_module): """ Verify that valid snmp peering db objects are . :param mocked_worker_module: fixture """ peering_list_schema = { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "peering": { "type": "object", "properties": { "local": {"type": "string"}, "remote": {"type": "string"}, "oid": {"type": "string"}, "community": {"type": "string"}, "hostname": {"type": "string"} }, "required": ["local", "remote", "oid", "community", "hostname"], "additionalProperties": False } }, "type": "array", "items": {"$ref": "#/definitions/peering"} } db = backend_db() # also forces initialization def _x(k): if not k.startswith('snmp-peerings'): return False if k.startswith('snmp-peerings:hosts:'): return False return True for k in list(filter(_x, db.keys())): del db[k] worker._build_snmp_peering_db() found_record = False for key, value in db.items(): if not _x(key): continue value = json.loads(value) jsonschema.validate(value, peering_list_schema) assert value found_record = True assert found_record def test_update_interfaces_to_services(mocker, mocked_worker_module): test_data = [ {'equipment': 'eqa', 'interface_name': 'ifca', 'x': 99}, {'equipment': 'eqb', 'interface_name': 'ifcb', 'z': {'a': 1}} ] get_circuits = mocker.patch('inventory_provider.db.opsdb.get_circuits') get_circuits.return_value = test_data db = backend_db() # also forces initialization db.clear() worker.update_interfaces_to_services() for service in test_data: key = 'opsdb:interface_services:{equipment}:{interface_name}'.format( **service) cached_service = json.loads(db[key]) assert cached_service == [service]