Skip to content
Snippets Groups Projects
Commit 767bd6b0 authored by Erik Reid's avatar Erik Reid
Browse files

Finished feature NGM-20-remove-map-services.

parents 604b6bd5 5926e4d5
No related branches found
No related tags found
No related merge requests found
......@@ -19,70 +19,18 @@ static inventory information relevant to maps.
.. autofunction:: inventory_provider.routes.map.equipment
/map/services/<service-type>
---------------------------------
.. autofunction:: inventory_provider.routes.map.services
/map/service-types
---------------------------------
.. autofunction:: inventory_provider.routes.map.service_types
"""
import json
import logging
import re
from flask import Blueprint, Response, request, jsonify
from flask import Blueprint, jsonify
import jsonschema
from inventory_provider.routes import common
from inventory_provider.routes import msr
logger = logging.getLogger(__name__)
routes = Blueprint('map-support-routes', __name__)
SERVICE_LIST_SCHEMA = {
'$schema': 'https://json-schema.org/draft/2020-12/schema',
'definitions': {
'service': {
'type': 'object',
'properties': {
'sid': {'type': 'string'},
'name': {'type': 'string'},
'type': {'type': 'string'},
'pops': {
'type': 'array',
'items': {'type': 'string'}
},
'overlays': {
'type': 'object',
'properties': {
'speed': {'type': 'number'},
}
},
},
'required': ['sid', 'name', 'type', 'pops', 'overlays'],
'additionalProperties': False
},
},
'type': 'array',
'items': {'$ref': '#/definitions/service'}
}
SERVICE_TYPE_LIST_SCHEMA = {
'$schema': 'https://json-schema.org/draft/2020-12/schema',
'type': 'array',
'items': {'type': 'string'}
}
EQUIPMENT_LIST_SCHEMA = {
'$schema': 'https://json-schema.org/draft/2020-12/schema',
......@@ -127,127 +75,6 @@ POP_LIST_SCHEMA = {
}
def _load_all_services():
r = common.get_current_redis()
equipment_list = json.loads(r.get('ims:map:equipment').decode('utf-8'))
equipment_dict = {_x['name']: _x for _x in equipment_list}
def _operational(s):
return s["status"].lower() == "operational"
def _hostname_to_equipment(_hn):
m = re.match(r'^(.+)\.geant\.net$', _hn)
if not m:
logger.error(f'unexpected hostname pattern: {_hn}')
return '?'
return m.group(1).upper()
def _endpoint_to_pop(_endpoint: dict[str, str]) -> str:
if 'hostname' in _endpoint:
eq_name = _hostname_to_equipment(_endpoint['hostname'])
elif 'equipment' in _endpoint:
eq_name = _endpoint['equipment']
else:
logger.error(f'no equipment or hostname in endpoint: {_endpoint}')
return '?'
if eq_name not in equipment_dict:
# TODO: is this really possible if all data is read from IMS at the same time?
logger.error(f"unknown endpoint equipment: {eq_name}")
return '?'
return equipment_dict[eq_name]['pop']
def _reformat_service(s):
_pops = map(_endpoint_to_pop, s["endpoints"])
return {
"name": s["name"],
"pops": list(_pops),
"sid": s["sid"],
"type": s["service_type"],
"overlays": {
"speed": s["speed"],
}
}
cache_key_all_services = "classifier-cache:map:services"
all_map_service_info = common._ignore_cache_or_retrieve(request, cache_key_all_services, r)
if all_map_service_info:
all_map_service_info = json.loads(all_map_service_info)
else:
msr_services = filter(_operational, msr.load_all_msr_services())
all_map_service_info = map(_reformat_service, msr_services)
all_map_service_info = list(all_map_service_info)
r.set(cache_key_all_services, json.dumps(all_map_service_info))
return all_map_service_info
@routes.route("/services", methods=['GET'])
@routes.route('/services/<service_type>', methods=['GET'])
@common.require_accepts_json
def services(service_type=None):
"""
Handler for `/map/services` and
`/map/services/<service_type>`
which returns information for either all services
or those of a specific service type.
This endpoint is used by the mapping-provider to get
static information about all operationalservices.
.. asjson::
inventory_provider.routes.map.SERVICE_LIST_SCHEMA
:param service_type: optional filter on service name
:return: list of services
"""
result = _load_all_services()
if service_type:
result = [s for s in result if s["type"] == service_type]
if not result:
message = f'no {service_type} services found' \
if service_type else 'no services found'
return Response(
response=message,
status=404,
mimetype='text/html')
return jsonify(result)
@routes.route("/service-types", methods=['GET'])
@common.require_accepts_json
def service_types():
"""
Handler for `/map/service-types` which returns
all known operationalservice types in the network
This endpoint is used by the mapping-provider to get
static information about all operationalservices.
.. asjson::
inventory_provider.routes.map.SERVICE_LIST_SCHEMA
:return: list of service types
"""
service_types = set([s["type"] for s in _load_all_services()])
if not service_types:
return Response(
response='no service types found',
status=404,
mimetype='text/html')
return jsonify(list(service_types))
@routes.route("/equipment", methods=['GET'])
@common.require_accepts_json
def equipment(service_type=None):
......
import json
import jsonschema
import pytest
from inventory_provider.routes import map
def test_get_all_services(client):
rv = client.get(
'/map/services',
headers={'Accept': ['application/json']})
assert rv.status_code == 200
assert rv.is_json
response_data = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(response_data, map.SERVICE_LIST_SCHEMA)
assert response_data # test data is non-empty
@pytest.mark.parametrize(
'service_type', [
'ETHERNET',
'IP TRUNK',
'GEANT IP',
'IP PEERING - R&E'])
def test_get_services_by_type(client, service_type):
rv = client.get(
f'/map/services/{service_type}',
headers={'Accept': ['application/json']})
assert rv.status_code == 200
assert rv.is_json
response_data = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(response_data, map.SERVICE_LIST_SCHEMA)
assert response_data # test data is non-empty
def test_get_service_types(client):
rv = client.get(
'/map/service-types',
headers={'Accept': ['application/json']})
assert rv.status_code == 200
assert rv.is_json
response_data = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(response_data, map.SERVICE_TYPE_LIST_SCHEMA)
assert response_data # test data is non-empty
print(json.dumps(response_data, indent=2))
def test_get_equipment(client):
rv = client.get(
'/map/equipment',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment