diff --git a/Changelog.md b/Changelog.md index 8cf38b9637dd8a591b83ed844cf0a0197760af12..c1794c28604285fcef98d7ac76f69d804729c663 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,9 @@ All notable changes to this project will be documented in this file. +## [0.53] - 2020-09-23 +- DBOARD-328: fixed improper response when router is unknown + ## [0.52] - 2020-09-07 - POL1-228 (and others): - allow /poller/interfaces to be called without an argument diff --git a/inventory_provider/routes/classifier.py b/inventory_provider/routes/classifier.py index 1673e80744ec617f0cd2c120f751dc5416a70f76..a9e5e21173e2ff2d3351d8efcfb317626189c46c 100644 --- a/inventory_provider/routes/classifier.py +++ b/inventory_provider/routes/classifier.py @@ -33,24 +33,24 @@ def _remove_duplicates_from_list(all): return list(tmp_dict.values()) -def _location_from_router(router_name): +def _locations_from_router(router_name): r = common.get_current_redis() result = r.get(f'opsdb:location:{router_name}') if not result: logger.error(f'error looking up location for {router_name}') - return None + return [] result = json.loads(result.decode('utf-8')) if not result: logger.error(f'sanity failure: empty list for location {router_name}') - return None + return [] - return { + return [{ 'a': _LOCATION( equipment=result[0]['equipment-name'], name=result[0]['pop']['name'], abbreviation=result[0]['pop']['abbreviation']) - } + }] def _location_from_service_dict(s): @@ -206,7 +206,7 @@ def get_juniper_link_info(source_equipment, interface): result['related-services'] = top_level_services if not result['locations']: - result['locations'] = [_location_from_router(source_equipment)] + result['locations'] = _locations_from_router(source_equipment) result['locations'] = _remove_duplicates_from_list(result['locations']) result = json.dumps(result) @@ -340,16 +340,14 @@ def peer_info(address): info = info.decode('utf-8') info = json.loads(info) result['ix-public-peer-info'] = ix_peering_info(info) - router_location = _location_from_router(info['router']) - result['locations'] += [router_location] + result['locations'] += _locations_from_router(info['router']) info = r.get('vpn_rr_peer:%s' % address) if info: info = info.decode('utf-8') info = json.loads(info) result['vpn-rr-peer-info'] = info - router_location = _location_from_router(info['router']) - result['locations'] += [router_location] + result['locations'] += _locations_from_router(info['router']) interfaces = list(find_interfaces_and_services(address)) if interfaces: diff --git a/setup.py b/setup.py index 5e1f82a7606e8c74ffd5a48bf7db90ff2dc8d258..7535f07008d89e11429aaaed07d2c852060734c4 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name='inventory-provider', - version="0.52", + version="0.53", author='GEANT', author_email='swd@geant.org', description='Dashboard inventory provider', diff --git a/test/test_classifier_routes.py b/test/test_classifier_routes.py index 4afac35968354d664183242e34654c3907e18cab..5de175c93a72f52874f8403048dc1cf5707dedad 100644 --- a/test/test_classifier_routes.py +++ b/test/test_classifier_routes.py @@ -174,7 +174,7 @@ JUNIPER_LINK_METADATA = { }, "locations": {"$ref": "#/definitions/locations-list"} }, - # "required": ["interface"], + "required": ["interface", "locations"], "additionalProperties": False } @@ -216,6 +216,28 @@ def test_juniper_link_info_not_found(client): } +def test_juniper_link_unknown_router(client): + rv = client.get( + '/classifier/juniper-link-info/' + 'unknown-router/unknown-interface-name', + headers=DEFAULT_REQUEST_HEADERS) + assert rv.status_code == 200 + assert rv.is_json + response_data = json.loads(rv.data.decode('utf-8')) + jsonschema.validate(response_data, JUNIPER_LINK_METADATA) + assert response_data == { + 'interface': { + 'name': 'unknown-interface-name', + 'description': '', + 'ipv4': [], + 'ipv6': [], + 'bundle': [], + 'bundle_members': [] + }, + 'locations': [] + } + + VPN_RR_PEER_INFO_KEYS = {'vpn-rr-peer-info', 'locations'} IX_PUBLIC_PEER_INFO_KEYS = {'ix-public-peer-info', 'interfaces', 'locations'}