diff --git a/inventory_provider/routes/data.py b/inventory_provider/routes/data.py index f5f780cebb9365eec28c8af7b0524931c78d0fba..f25bd80dae5374c1b43b3802e697a07327b6c137 100644 --- a/inventory_provider/routes/data.py +++ b/inventory_provider/routes/data.py @@ -27,23 +27,41 @@ def routers(): return jsonify(result) +@routes.route("/interfaces", methods=['GET', 'POST']) @routes.route("/interfaces/<hostname>", methods=['GET', 'POST']) @common.require_accepts_json -def router_interfaces(hostname): - r = common.get_current_redis() - interfaces = [] - for k in r.keys('netconf-interfaces:%s:*' % hostname): - ifc = r.get(k.decode('utf-8')) - if ifc: - interfaces.append(json.loads(ifc.decode('utf-8'))) +def router_interfaces(hostname=None): - if not interfaces: - return Response( - response="no available interface info for '%s'" % hostname, - status=404, - mimetype="text/html") + cache_key = f'classifier-cache:netconf-interfaces:{hostname}' \ + if hostname else 'classifier-cache:netconf-interfaces:all' - return jsonify(interfaces) + r = common.get_current_redis() + result = r.get(cache_key) + if result: + result = result.decode('utf-8') + + else: + key_pattern = f'netconf-interfaces:{hostname}:*' \ + if hostname else 'netconf-interfaces:*' + config = current_app.config['INVENTORY_PROVIDER_CONFIG'] + + result = [] + for ifc in common.load_json_docs(config, key_pattern): + key_fields = ifc['key'].split(':') + ifc['value']['router'] = key_fields[1] + result.append(ifc['value']) + + if not result: + return Response( + response="no available interface info for '%s'" % hostname, + status=404, + mimetype="text/html") + + result = json.dumps(result) + # cache this data for the next call + r.set(cache_key, result.encode('utf-8')) + + return Response(result, mimetype="application/json") @routes.route("/pop/<equipment_name>", methods=['GET', 'POST']) diff --git a/test/per_router/test_data_routes.py b/test/per_router/test_data_routes.py index 063aa2a3e13b49ff9df6fc3d07953edfbaa4806c..85fa9bae5600f70bca58615dd67b117f33145c62 100644 --- a/test/per_router/test_data_routes.py +++ b/test/per_router/test_data_routes.py @@ -18,6 +18,7 @@ def test_router_interfaces(router, client): "properties": { "name": {"type": "string"}, "description": {"type": "string"}, + "router": {"type": "string"}, "bundle": { "type": "array", "items": {"type": "string"} @@ -31,7 +32,7 @@ def test_router_interfaces(router, client): "items": {"type": "string"} } }, - "required": ["name", "description", "ipv4", "ipv6"], + "required": ["name", "description", "ipv4", "router", "ipv6"], "additionalProperties": False } } diff --git a/test/test_general_data_routes.py b/test/test_general_data_routes.py index fa8c385aa5866a4a77b583f43cb0c940831c676e..a618f8fb2c7ff6a0e01530511ce3fba166ef9a23 100644 --- a/test/test_general_data_routes.py +++ b/test/test_general_data_routes.py @@ -75,3 +75,42 @@ def test_pop_not_found(client, mocker): headers=DEFAULT_REQUEST_HEADERS) assert rv.status_code == 404 + + +def test_router_interfaces_all(client): + + interfaces_list_schema = { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "description": {"type": "string"}, + "router": {"type": "string"}, + "bundle": { + "type": "array", + "items": {"type": "string"} + }, + "ipv4": { + "type": "array", + "items": {"type": "string"} + }, + "ipv6": { + "type": "array", + "items": {"type": "string"} + } + }, + "required": ["name", "description", "ipv4", "router", "ipv6"], + "additionalProperties": False + } + } + + rv = client.post( + '/data/interfaces', + headers=DEFAULT_REQUEST_HEADERS) + + assert rv.status_code == 200 + response = json.loads(rv.data.decode("utf-8")) + jsonschema.validate(response, interfaces_list_schema) + assert response # at least shouldn't be empty