Skip to content
Snippets Groups Projects
Commit 1339e8ec authored by Release Webservice's avatar Release Webservice
Browse files

Finished release 0.91.

parents 530072dc fca3886f
Branches
Tags 0.91
No related merge requests found
......@@ -2,6 +2,9 @@
All notable changes to this project will be documented in this file.
## [0.91] - 2022-08-03
- REPORTING-311: Added /msr/asn-peers endpoint
## [0.90] - 2022-07-19
- REPORTING-297: Add /msr/mdvpn endpoint
- REPORTING-307: Add /msr/vpn-proxy endpoint
......
......@@ -74,7 +74,13 @@ These endpoints are intended for use by MSR.
/msr/vpn-proxy
--------------------------------------------
.. autofunction:: inventory_provider.routes.msr.vpn-proxy
.. autofunction:: inventory_provider.routes.msr.vpn_proxy
/msr/asn-peers
--------------------------------------------
.. autofunction:: inventory_provider.routes.msr.asn_peers
helpers
......@@ -356,6 +362,40 @@ DOMAIN_TO_POP_MAPPING = {
"ams.nl": "Amsterdam"
}
# very similar to PEERING_LIST_SCHEMA but
# with a field for NREN, which is required
ASN_PEER_LIST_SCHEMA = {
'$schema': 'http://json-schema.org/draft-07/schema#',
'definitions': {
'peering-instance': {
'type': 'object',
'properties': {
'address': {'type': 'string'},
'description': {'type': 'string'},
'logical-system': {'type': 'string'},
'group': {'type': 'string'},
'hostname': {'type': 'string'},
'remote-asn': {'type': 'integer'},
'local-asn': {'type': 'integer'},
'instance': {'type': 'string'},
'nren': {'type': 'string'}
},
# only vrr peerings have remote-asn
# only group peerings have local-asn or instance
# not all group peerings have 'description'
# and only vrr or vpn-proxy peerings are within a logical system
'required': [
'address',
'group',
'hostname',
'nren'],
'additionalProperties': False
}
},
'type': 'array',
'items': {'$ref': '#/definitions/peering-instance'}
}
@routes.after_request
def after_request(resp):
......@@ -1173,3 +1213,88 @@ def vpn_proxy():
peerings = list(_format_peerings(vpnproxy))
response = json.dumps(peerings)
return Response(response, mimetype='application/json')
@routes.route('/asn-peers', methods=['GET', 'POST'], defaults={'asn': None})
@routes.route('/asn-peers/<int:asn>', methods=['GET', 'POST'])
@common.require_accepts_json
def asn_peers(asn):
"""
Handler for `/asn-peers`
This method returns a list of all peers filtered by `group` and `instance`,
which can be passed either as URL query parameters or as entries in a
POST request with a JSON body that matches this schema:
`{
"group": "group to filter by",
"instance": "instance to filter by"
}`
Results are returned where all filters given are true, and exact string
matches.
An optional URL parameter can be used to also filter by a specific ASN.
The response will be formatted according to the following schema:
.. asjson::
inventory_provider.routes.msr.ASN_PEER_LIST_SCHEMA
:param asn: specific ASN to get peers for
:return:
"""
r = common.get_current_redis()
def _get_filtered_peers_for_asn(asn, nren, group, instance):
peers = json.loads(r.get(f'juniper-peerings:peer-asn:{asn}'))
def _attribute_filter(peer, name, value):
if value is None:
return True # no filter parameter given in request
if name not in peer:
return False # no value exists, cannot meet condition
return peer[name] == value
for peer in peers:
if _attribute_filter(peer, "group", group) and \
_attribute_filter(peer, "instance", instance):
peer['nren'] = nren
yield peer
def _get_filtered_peers(asn_nren_map, group, instance):
for asn, nren in asn_nren_map.items():
asn_peers = _get_filtered_peers_for_asn(asn, nren, group, instance)
for peer in asn_peers:
yield peer
# handle getting parameters regardless of method of input
if request.method == 'GET':
group = request.args.get('group')
instance = request.args.get('instance')
else:
params = json.loads(request.json)
group = params.get('group', None)
instance = params.get('instance', None)
cache_key = f'classifier-cache:msr:asn-peers:{asn}:{group}:{instance}'
response = _ignore_cache_or_retrieve(request, cache_key, r)
if not response:
config = current_app.config['INVENTORY_PROVIDER_CONFIG']
# set up quick lookup based on ASN
asn_nren_map = {
item['asn']: item['nren'] for item in config['nren-asn-map']
}
if asn is not None:
nren = asn_nren_map.get(asn, None)
peers = list(
_get_filtered_peers_for_asn(asn, nren, group, instance)
)
else:
peers = list(
_get_filtered_peers(asn_nren_map, group, instance)
)
response = json.dumps(peers)
r.set(cache_key, response.encode('utf-8'))
return Response(response, mimetype='application/json')
......@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name='inventory-provider',
version="0.90",
version="0.91",
author='GEANT',
author_email='swd@geant.org',
description='Dashboard inventory provider',
......
......@@ -72,6 +72,10 @@ def data_config_filename():
{
"nren": "BAT",
"asn": 2200
},
{
"nren": "BAZ",
"asn": 1853
}
]
}
......
......@@ -6,7 +6,7 @@ import pytest
from inventory_provider.routes.msr import PEERING_LIST_SCHEMA, \
PEERING_GROUP_LIST_SCHEMA, PEERING_ADDRESS_SERVICES_LIST, \
SYSTEM_CORRELATION_SERVICES_LIST_SCHEMA, _get_services_for_address, \
MDVPN_LIST_SCHEMA, VPN_PROXY_LIST_SCHEMA
MDVPN_LIST_SCHEMA, VPN_PROXY_LIST_SCHEMA, ASN_PEER_LIST_SCHEMA
from inventory_provider.routes.poller import SERVICES_LIST_SCHEMA
from inventory_provider.tasks.common import _get_redis
......@@ -346,3 +346,48 @@ def test_get_vpn_proxy_peerings(client, mocked_redis):
response_data = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(response_data, VPN_PROXY_LIST_SCHEMA)
assert response_data # test data is non-empty
@pytest.mark.parametrize('endpoint_variant', [
"", # default, no filter
"/1853",
"?group=IAS-NRENS",
"?instance=IAS",
"?group=IAS-NRENS&instance=IAS",
"/1853?group=IAS-NRENS",
"/1853?instance=IAS",
"/1853?group=IAS-NRENS&instance=IAS"
])
def test_get_asn_peers_get(endpoint_variant, client, mocked_redis):
rv = client.get(
f'/msr/asn-peers{endpoint_variant}',
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, ASN_PEER_LIST_SCHEMA)
assert response_data # test data is non-empty
@pytest.mark.parametrize('endpoint_variant,post_body', [
("", '{}'),
("", '{"group": "IAS-NRENS"}'),
("", '{"instance": "IAS"}'),
("", '{"group": "IAS-NRENS", "instance": "IAS"}'),
("/1853", '{}'),
("/1853", '{"group": "IAS-NRENS"}'),
("/1853", '{"instance": "IAS"}'),
("/1853", '{"group": "IAS-NRENS", "instance": "IAS"}')
])
def test_get_asn_peers_post(endpoint_variant, post_body, client, mocked_redis):
rv = client.post(
f'/msr/asn-peers{endpoint_variant}',
headers=DEFAULT_REQUEST_HEADERS,
json=post_body
)
assert rv.status_code == 200
assert rv.is_json
response_data = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(response_data, ASN_PEER_LIST_SCHEMA)
assert response_data # test data is non-empty
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment