diff --git a/inventory_provider/routes/classifier.py b/inventory_provider/routes/classifier.py index 0d66e89e4b3da1af595967f812a3d0026ebee137..7ca418517acf14bfab8018375e7069ba991a865a 100644 --- a/inventory_provider/routes/classifier.py +++ b/inventory_provider/routes/classifier.py @@ -1,3 +1,4 @@ +import ipaddress import json from flask import Blueprint, Response, jsonify @@ -49,6 +50,35 @@ def get_trap_metadata(source_equipment, interface): @common.require_accepts_json def peer_info(address): + def _related_ix_peers(ix_public_peer_info): + """ + TODO: this is probably the least efficient way of doing this + (if it's a problem, pre-compute these lists) + + :param ix_public_peer_info: ix public peer info loaded for address + :return: + """ + + protocol = type(ipaddress.ip_address(address)).__name__ + + description = ix_public_peer_info['description'] + assert description is not None # sanity: at least empty string + keyword = description.split(' ')[0] # regex needed??? (e.g. tabs???) + + r = common.get_redis() + + for k in r.keys('ix_public_peer:*'): + peer = r.get(k.decode('utf-8')).decode('utf-8') + peer = json.loads(peer) + assert peer['description'] is not None # sanity: as above... + if not peer['description'].startswith(keyword): + continue + if peer['name'] == address: + continue # skip self + peer_address = ipaddress.ip_address(peer['name']) + if protocol == type(peer_address).__name__: + yield peer['name'] + r = common.get_redis() result = {} @@ -57,6 +87,8 @@ def peer_info(address): if info: info = info.decode('utf-8') result['ix-public-peer-info'] = json.loads(info) + result['ix-public-peer-group'] = list( + _related_ix_peers(result['ix-public-peer-info'])) info = r.get('vpn_rr_peer:%s' % address) if info: diff --git a/test/test_classifier_routes.py b/test/test_classifier_routes.py index bd783d52c388d2a18caa352ed4b697ec50da014e..792915330cc3ea3447e78896ffbac6663c21c3b2 100644 --- a/test/test_classifier_routes.py +++ b/test/test_classifier_routes.py @@ -22,14 +22,19 @@ def test_trap_metadata(client_with_mocked_data): jsonschema.validate(response_data, response_schema) -@pytest.mark.parametrize("peer_address,peer_type", [ - ('109.105.110.54', 'vpn-rr-peer-info'), - ('2001:07f8:001c:024a:0000:0000:316e:0001', 'ix-public-peer-info'), - ('2001:07f8:000b:0100:01d1:a5d1:0310:0029', 'ix-public-peer-info'), - ('195.66.224.238', 'ix-public-peer-info'), +VPN_RR_PEER_INFO_KEYS = {'vpn-rr-peer-info'} +IX_PUBLIC_PEER_INFO_KEYS = {'ix-public-peer-info', 'ix-public-peer-group'} + + +@pytest.mark.parametrize("peer_address,expected_response_keys", [ + ('109.105.110.54', VPN_RR_PEER_INFO_KEYS), + ('2001:07f8:001c:024a:0000:0000:316e:0001', IX_PUBLIC_PEER_INFO_KEYS), + ('2001:07f8:000b:0100:01d1:a5d1:0310:0029', IX_PUBLIC_PEER_INFO_KEYS), + ('195.66.224.238', IX_PUBLIC_PEER_INFO_KEYS), ] ) -def test_peer_info(client_with_mocked_data, peer_address, peer_type): +def test_peer_info( + client_with_mocked_data, peer_address, expected_response_keys): response_schema = { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", @@ -53,7 +58,6 @@ def test_peer_info(client_with_mocked_data, peer_address, peer_type): "required": ["name", "description"], "additionalProperties": False }, - "ix-public-peer": { "type": "object", "properties": { @@ -72,12 +76,18 @@ def test_peer_info(client_with_mocked_data, peer_address, peer_type): }, "required": ["name", "description", "as"], "additionalProperties": False - } + }, + "ix-public-peer-group": { + "type": "array", + "items": {"$ref": "#/definitions/ip-address"} + }, + }, "type": "object", "properties": { "ix-public-peer-info": {"$ref": "#/definitions/ix-public-peer"}, + "ix-public-peer-group": {"$ref": "#/definitions/ix-public-peer-group"}, "vpn-rr-peer-info": {"$ref": "#/definitions/vpn-rr-peer"} }, "additionalProperties": False @@ -91,10 +101,7 @@ def test_peer_info(client_with_mocked_data, peer_address, peer_type): response_data = json.loads(rv.data.decode('utf-8')) jsonschema.validate(response_data, response_schema) - assert len(response_data) == 1, \ - "peer should be only vpn-rr or ix-public, not both" - - assert peer_type in response_data + assert set(response_data.keys()) == expected_response_keys def test_peer_not_found(client_with_mocked_data):