From 585842daad2f6081b48b68b76c163e9ec76c64de Mon Sep 17 00:00:00 2001
From: Erik Reid <erik.reid@geant.org>
Date: Fri, 12 Apr 2019 15:56:08 +0200
Subject: [PATCH] moved some parsing into coriant classifier handler

---
 inventory_provider/routes/classifier.py | 42 ++++++++++++++++---------
 test/test_classifier_routes.py          | 32 +++++++++++++------
 2 files changed, 49 insertions(+), 25 deletions(-)

diff --git a/inventory_provider/routes/classifier.py b/inventory_provider/routes/classifier.py
index 0cfac3b4..90b8d9da 100644
--- a/inventory_provider/routes/classifier.py
+++ b/inventory_provider/routes/classifier.py
@@ -1,5 +1,6 @@
 import ipaddress
 import json
+import logging
 import re
 
 from flask import Blueprint, Response, current_app
@@ -9,6 +10,8 @@ from inventory_provider.db import opsdb, db
 
 routes = Blueprint("inventory-data-classifier-support-routes", __name__)
 
+logger = logging.getLogger(__name__)
+
 
 class ClassifierRequestError(Exception):
     status_code = 500
@@ -280,37 +283,46 @@ def get_trap_metadata(source_equipment, interface, circuit_id):
     return Response(result, mimetype="application/json")
 
 
-@routes.route("/coriant-info/"
-              "<equipment_name>/<card_id>/<port_number>",
+@routes.route('/coriant-info/<equipment_name>/<path:entity_string>',
               methods=['GET', 'POST'])
 @common.require_accepts_json
-def get_coriant_info(equipment_name, card_id, port_number):
+def get_coriant_info(equipment_name, entity_string):
     r = common.get_redis()
 
-    cache_key = 'classifier-cache:coriant:%s:%s:%s' % (
-        equipment_name, card_id, port_number)
+    cache_key = 'classifier-cache:coriant:%s:%s' % (
+        equipment_name, entity_string)
     result = r.get(cache_key)
 
     if result:
         result = result.decode('utf-8')
     else:
 
+        m = re.match(r'^(\d+\-\d+)\.(\d+)', entity_string)
+        if not m:
+            logger.warning(
+                'invalid coriant entity string format: %r' % entity_string)
+            return Response(
+                response="no available info for '{}' '{}'".format(
+                    equipment_name, entity_string),
+                status=404,
+                mimetype="text/html")
+        result = {
+            'equipment name': equipment_name,
+            'card id': m.group(1),
+            'port number': m.group(2)
+        }
+
         config = current_app.config['INVENTORY_PROVIDER_CONFIG']
 
         with db.connection(config['ops-db']) as cx:
             path = opsdb.lookup_coriant_path(
-                cx, equipment_name, card_id, port_number)
+                cx, equipment_name, result['card id'], result['port number'])
 
-        if not path:
-            return Response(
-                response="no available info for {} {} {}".format(
-                    equipment_name, card_id, port_number),
-                status=404,
-                mimetype="text/html")
-
-        result = json.dumps({'path': path})
+        if path:
+            result['path'] = path
 
         # cache this data for the next call
-        r.set(cache_key, result.encode('utf-8'))
+        result = json.dumps(result).encode('utf-8')
+        r.set(cache_key, result)
 
     return Response(result, mimetype="application/json")
diff --git a/test/test_classifier_routes.py b/test/test_classifier_routes.py
index 413565fd..65aca5f9 100644
--- a/test/test_classifier_routes.py
+++ b/test/test_classifier_routes.py
@@ -278,16 +278,14 @@ def test_coriant_info(client, mocker):
     """
     just check the correct method is called, but mock out all sql access
     """
-    expected_path = {
-        'C': 'bogus connection',
-        'E': 'bogus equipment name',
-        'CID': 'bogus card id',
-        'P': 'bogus card number'
-    }
+    CONNECTION = 'bogus connection'
+    EQUIPMENT = 'bogus equipment name'
+    CARD_ID = '123-456'
+    PORT_NUMBER = '789'
 
     @contextlib.contextmanager
     def mocked_connection(ignored):
-        yield expected_path['C']
+        yield CONNECTION
 
     mocker.patch(
         'inventory_provider.db.db.connection', mocked_connection)
@@ -296,14 +294,28 @@ def test_coriant_info(client, mocker):
         lambda a, b, c, d: {'C': a, 'E': b, 'CID': c, 'P': d})
 
     rv = client.get(
-        '/classifier/coriant-info/{E}/{CID}/{P}'.format(**expected_path),
+        '/classifier/coriant-info/{eq}/{cid}.{pn}abc.234 af/23'.format(
+            eq=EQUIPMENT,
+            cid=CARD_ID,
+            pn=PORT_NUMBER),
         headers=DEFAULT_REQUEST_HEADERS)
 
     assert rv.status_code == 200
     assert rv.is_json
     response_data = json.loads(rv.data.decode('utf-8'))
 
-    expected_response = {'path': expected_path}
+    expected_response = {
+        'equipment name': EQUIPMENT,
+        'card id': CARD_ID,
+        'port number': PORT_NUMBER,
+        'path': {
+            'C': CONNECTION,
+            'E': EQUIPMENT,
+            'CID': CARD_ID,
+            'P': PORT_NUMBER
+        }
+    }
+
     assert response_data == expected_response
 
 
@@ -323,7 +335,7 @@ def test_coriant_info_not_found(client, mocker):
         lambda a, b, c, d: None)
 
     rv = client.get(
-        '/classifier/coriant-info/aaa/bbb/ccc',
+        '/classifier/coriant-info/aaa/unparseableentitystring',
         headers=DEFAULT_REQUEST_HEADERS)
 
     assert rv.status_code == 404
-- 
GitLab