Skip to content
Snippets Groups Projects

Feature/reporting 311 add msr asn peers

Merged Sam Roberts requested to merge feature/REPORTING-311-add-msr-asn-peers into develop
All threads resolved!
Files
3
@@ -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')
Loading