From a96711562113de4161599fbadd8a5472cfea5ba8 Mon Sep 17 00:00:00 2001
From: Erik Reid <erik.reid@geant.org>
Date: Thu, 13 Aug 2020 16:10:58 +0200
Subject: [PATCH] use load_json_docs for /data/interfaces, added router to
 response

---
 inventory_provider/routes/data.py   | 44 ++++++++++++++++++++---------
 test/per_router/test_data_routes.py |  3 +-
 test/test_general_data_routes.py    | 39 +++++++++++++++++++++++++
 3 files changed, 72 insertions(+), 14 deletions(-)

diff --git a/inventory_provider/routes/data.py b/inventory_provider/routes/data.py
index f5f780ce..f25bd80d 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 063aa2a3..85fa9bae 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 fa8c385a..a618f8fb 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
-- 
GitLab