Skip to content
Snippets Groups Projects
Commit 5c8be61a authored by Robert Latta's avatar Robert Latta
Browse files

removed redundant endpoints

parent aa955989
Branches
Tags
No related merge requests found
...@@ -13,7 +13,6 @@ These endpoints are intended for use by the Maintenance Impact Calculator tool ...@@ -13,7 +13,6 @@ These endpoints are intended for use by the Maintenance Impact Calculator tool
""" """
import itertools
import json import json
import logging import logging
from collections import defaultdict from collections import defaultdict
...@@ -26,54 +25,37 @@ from inventory_provider.routes.common import _ignore_cache_or_retrieve ...@@ -26,54 +25,37 @@ from inventory_provider.routes.common import _ignore_cache_or_retrieve
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
routes = Blueprint('mic-support-routes', __name__) routes = Blueprint('mic-support-routes', __name__)
SITES_LIST_SCHEMA = {
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"abbreviation": {"type": "string"}
},
"required": ["name", "abbreviation"],
"additionalProperties": False
}
}
NODES_LIST_SCHEMA = {
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "array",
"items": {"type": "string"},
"additionalProperties": False
}
INTERFACES_LIST_SCHEMA = { ALL_DATA_SCHEMA = {
"$schema": "https://json-schema.org/draft-07/schema#", "schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {"type": "string"},
"additionalProperties": False
}
IMPACT_SCHEMA = {
"schema": "http:json-schema.org/draft-07/schema#",
"type": "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*$": { "^.*$": {
"type": "array", "type": "object",
"items": { "patternProperties": {
"type": "object", "^.*$": {
"properties": { "type": "object",
"id": {"type": "integer"}, "patternProperties": {
"sid": {"type": "string"}, "^.*$": {
"name": {"type": "string"}, "type": "array",
"service_type": {"type": "string"}, "items": {
"contacts": { "type": "object",
"type": "array", "properties": {
"items": {"type": "string"} "id": {"type": "integer"},
"sid": {"type": "string"},
"name": {"type": "string"},
"service_type": {"type": "string"},
"contacts": {
"type": "array",
"items": {"type": "string"}
}
},
"required": ["id", "sid", "name", "service_type", "contacts"], # noqa E501
"additionalProperties": False
}
}
} }
}, }
"required": ["id", "sid", "name", "service_type", "contacts"],
"additionalProperties": False
} }
} }
}, },
...@@ -81,121 +63,6 @@ IMPACT_SCHEMA = { ...@@ -81,121 +63,6 @@ IMPACT_SCHEMA = {
} }
@routes.route('/sites')
def get_sites():
cache_key = 'classifier-cache:mic:sites'
r = common.get_current_redis()
result = _ignore_cache_or_retrieve(request, cache_key, r)
if not result:
def _fetch_sites():
config = current_app.config['INVENTORY_PROVIDER_CONFIG']
for doc in common.load_json_docs(
config_params=config,
key_pattern='ims:pop:*'
):
yield {
'name': doc['value']['name'],
'abbreviation': doc['value']['abbreviation'],
}
sites = sorted(_fetch_sites(), key=lambda x: x['name'])
result = json.dumps(sites)
r.set(cache_key, result.encode('utf-8'))
return Response(result, mimetype='application/json')
@routes.route('/nodes/<site>')
def get_nodes(site):
cache_key = f'classifier-cache:mic:nodes:{site}'
r = common.get_current_redis()
result = _ignore_cache_or_retrieve(request, cache_key, r)
if not result:
result = r.get(f'ims:pop_nodes:{site}')
if result:
r.set(cache_key, result)
result = result.decode('utf-8')
return Response(result, mimetype='application/json')
@routes.route('/interfaces/<node>')
def get_interfaces(node):
cache_key = f'classifier-cache:mic:interfaces:{node}'
r = common.get_current_redis()
result = _ignore_cache_or_retrieve(request, cache_key, r)
if not result:
def _get_intefaces():
key_pattern = f"ims:interface_services:{node}:*"
for k in r.scan_iter(key_pattern, count=1000):
yield ":".join(k.decode('utf-8').split(':')[3:])
interfaces_ = sorted(_get_intefaces())
if interfaces_:
result = json.dumps(interfaces_)
r.set(cache_key, result.encode('utf-8'))
return Response(result, mimetype='application/json')
@routes.route('/impact/<site>', defaults={'node': None, 'interface_': None})
@routes.route('/impact/<site>/<node>', defaults={'interface_': None})
@routes.route('/impact/<site>/<node>/<path:interface_>')
def get_impact(site, node, interface_):
cache_key_end = ':'.join(filter(None, (site, node, interface_)))
cache_key = f"classifier-cache:mic:impact:{cache_key_end}"
logger.debug(cache_key)
r = common.get_current_redis()
result = _ignore_cache_or_retrieve(request, cache_key, r)
if not result:
data = []
config = current_app.config['INVENTORY_PROVIDER_CONFIG']
if interface_:
key_pattern = f"ims:interface_services:{node}:{interface_}"
raw_data = r.get(key_pattern)
if raw_data:
data = json.loads(raw_data.decode('utf-8'))
else:
def _get_data(_key_pattern):
for doc in common.load_json_docs(
config_params=config,
key_pattern=_key_pattern,
num_threads=20,):
yield from doc['value']
if node:
key_pattern = f"ims:interface_services:{node}:*"
else:
key_pattern = "ims:interface_services:*"
data = _get_data(key_pattern)
services_by_type = defaultdict(list)
if data:
rs = itertools.chain(
*(d.get('related-services', [])
for d in data if d['pop_name'] == site))
rs = filter(
lambda x: x['circuit_type'] == 'service'
and x['status'] == 'operational',
rs)
unique_services = sorted({d['id']: d for d in rs}.values(),
key=lambda x: x['name'])
try:
for service in unique_services:
services_by_type[service['service_type']].append({
'id': service['id'],
'sid': service.get('sid', ''),
'name': service['name'],
'service_type': service['service_type'],
'contacts': service['contacts']
})
except Exception as e:
logger.debug(json.dumps(service, indent=2))
raise e
result = json.dumps(services_by_type)
r.set(cache_key, result.encode('utf-8'))
return Response(result, mimetype='application/json')
@routes.route("/all-data") @routes.route("/all-data")
def get_everything(): def get_everything():
cache_key = "classifier-cache:mic:impact:all-data" cache_key = "classifier-cache:mic:impact:all-data"
...@@ -213,18 +80,24 @@ def get_everything(): ...@@ -213,18 +80,24 @@ def get_everything():
num_threads=20,): num_threads=20,):
yield from doc['value'] yield from doc['value']
def _get_formatted_rs(_d):
for rs in _d['related-services']:
if rs['status'] == 'operational':
yield {
'id': rs['id'],
'sid': rs.get('sid', ''),
'name': rs['name'],
'service_type': rs['service_type'],
'contacts': rs['contacts']
}
key_pattern = "ims:interface_services:*" key_pattern = "ims:interface_services:*"
data = _get_data(key_pattern) for d in _get_data(key_pattern):
if data: if d.get('related-services'):
site = f'{d["pop_name"]} ({d["pop_abbreviation"]})'
for d in data: eq_name = d['equipment']
if d.get('related-services'): if_name = d['port']
site = f'{d["pop_name"]} ({d["pop_abbreviation"]})' all_data[site][eq_name][if_name] = list(_get_formatted_rs(d))
eq_name = d['equipment']
if_name = d['port']
all_data[site][eq_name][if_name] = \
[rs for rs in d['related-services']
if rs['status'] == 'operational']
result = json.dumps(all_data) result = json.dumps(all_data)
r.set(cache_key, result.encode('utf-8')) r.set(cache_key, result.encode('utf-8'))
......
import json import json
import jsonschema import jsonschema
import pytest
from inventory_provider.routes.mic import SITES_LIST_SCHEMA, \ from inventory_provider.routes.mic import ALL_DATA_SCHEMA
NODES_LIST_SCHEMA, INTERFACES_LIST_SCHEMA, IMPACT_SCHEMA
DEFAULT_REQUEST_HEADERS = { DEFAULT_REQUEST_HEADERS = {
"Content-type": "application/json", "Content-type": "application/json",
...@@ -12,43 +10,11 @@ DEFAULT_REQUEST_HEADERS = { ...@@ -12,43 +10,11 @@ DEFAULT_REQUEST_HEADERS = {
} }
def test_get_sites(client, mocked_redis): def test_get_all_data(client, mocked_redis):
rv = client.get( rv = client.get(
'/mic/sites', '/mic/all-data',
headers=DEFAULT_REQUEST_HEADERS) headers=DEFAULT_REQUEST_HEADERS)
assert rv.status_code == 200 assert rv.status_code == 200
assert rv.is_json assert rv.is_json
response_data = json.loads(rv.data.decode('utf-8')) response_data = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(response_data, SITES_LIST_SCHEMA) jsonschema.validate(response_data, ALL_DATA_SCHEMA)
def test_get_nodes(client, mocked_redis):
rv = client.get(
'/mic/nodes/AMSTERDAM',
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, NODES_LIST_SCHEMA)
def test_get_interfaces(client, mocked_redis):
rv = client.get(
'/mic/interfaces/MX1.LON.UK',
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, INTERFACES_LIST_SCHEMA)
@pytest.mark.parametrize('endpoint', [
'/mic/impact/AMSTERDAM/MX1.AMS.NL/AE21',
'/mic/impact/LONDON/MX1.LON.UK',
'/mic/impact/GENEVA'])
def test_get_impact(endpoint, client, mocked_redis):
rv = client.get(endpoint, 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, IMPACT_SCHEMA)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment