From 52324066d89f21ac653aefdfce03de535b453ed4 Mon Sep 17 00:00:00 2001
From: Nikolay Stanchev <ns17@it-innovation.soton.ac.uk>
Date: Tue, 9 Apr 2019 11:12:54 +0100
Subject: [PATCH] Extends the GET alerts API endpoint

---
 src/service/clmcservice/alertsapi/tests.py | 26 +++++++++-------------
 src/service/clmcservice/alertsapi/views.py | 14 +++++++++---
 src/test/clmctest/alerts/test_alerts.py    | 10 +++++++++
 3 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/src/service/clmcservice/alertsapi/tests.py b/src/service/clmcservice/alertsapi/tests.py
index 64683d2..a24b597 100644
--- a/src/service/clmcservice/alertsapi/tests.py
+++ b/src/service/clmcservice/alertsapi/tests.py
@@ -302,6 +302,9 @@ class TestAlertsConfigurationAPI(object):
 
         kapacitor_host = self.config.registry.settings["kapacitor_host"]
         kapacitor_port = self.config.registry.settings["kapacitor_port"]
+        sfemc_fqdn = self.config.registry.settings["sfemc_fqdn"]
+        sfemc_port = self.config.registry.settings["sfemc_port"]
+        fqdn_prefix = "http://{0}:{1}/sfemc/event".format(sfemc_fqdn, sfemc_port)
 
         # test all of the test files provided by the path_generator_testfiles function, ignoring the last result, which is invalid resource spec. files
         for alert_spec_file_paths, valid_resource_spec_file_paths, _ in path_generator_testfiles():
@@ -338,12 +341,19 @@ class TestAlertsConfigurationAPI(object):
             # restructure the extracted alerts data to be comparable with the response of the clmc service
             expected_alerts = map(lambda alert_object: {
                 "policy": alert_object["policy"], "trigger": alert_object["trigger"],
+                # make sure handlers are sorted and replace URLs starting with the SFEMC fqdn prefix to the SFEMC label
+                "handlers": sorted(map(lambda handler: SFEMC if handler.startswith(fqdn_prefix) else handler, alert_object["handlers"].values())),
                 "task_identifier": alert_object["task"], "topic_identifier": alert_object["topic"],
                 "task_api_endpoint": "/kapacitor/v1/tasks/{0}".format(alert_object["task"]),
                 "topic_api_endpoint": "/kapacitor/v1/alerts/topics/{0}".format(alert_object["topic"]),
                 "topic_handlers_api_endpoint": "/kapacitor/v1/alerts/topics/{0}/handlers".format(alert_object["topic"])
             }, alerts)
             expected_alerts = sorted(expected_alerts, key=lambda x: x["trigger"])
+            # sort the handlers of each alert in the response to ensure comparison order is correct
+            for alert in response:
+                alert["handlers"] = sorted(alert["handlers"])
+
+            # compare the actual response with the expected response
             assert sorted(response, key=lambda x: x["trigger"]) == expected_alerts, "Incorrect result returned from a GET alerts request"
 
             clean_kapacitor_alerts(alerts, kapacitor_host, kapacitor_port)
@@ -388,21 +398,7 @@ class TestAlertsConfigurationAPI(object):
 
             # ensure that these resource (tasks, topics, handlers) exist in Kapacitor
             # traverse through all alerts and check that everything is created
-            for alert in alerts:
-                # check the alert task
-                alert_id = alert["task"]
-                kapacitor_response = get("http://{0}:{1}/kapacitor/v1/tasks/{2}".format(kapacitor_host, kapacitor_port, alert_id))
-                assert kapacitor_response.status_code == 200, "Alert with ID {0} was not created - test file {1}.".format(alert_id, alerts_test_file)
-
-                # check the alert topic
-                topic_id = alert["topic"]
-                kapacitor_response = get("http://{0}:{1}/kapacitor/v1/alerts/topics/{2}".format(kapacitor_host, kapacitor_port, topic_id))
-                assert kapacitor_response.status_code == 200, "Topic with ID {0} was not created - test file {1}".format(topic_id, alerts_test_file)
-
-                # check handlers
-                for handler_id in alert["handlers"]:
-                    kapacitor_response = get("http://{0}:{1}/kapacitor/v1/alerts/topics/{2}/handlers/{3}".format(kapacitor_host, kapacitor_port, topic_id, handler_id))
-                    assert kapacitor_response.status_code == 200, "Handler with ID {0} for topic with ID {1} was not created - test file {2}".format(handler_id, topic_id, alerts_test_file)
+            check_kapacitor_alerts(alerts, kapacitor_host, kapacitor_port, alerts_test_file)
 
             with open(alert_spec_abs_path) as alert_spec:
                 # now send the alert spec for deletion and check that everything is deleted in Kapacitor
diff --git a/src/service/clmcservice/alertsapi/views.py b/src/service/clmcservice/alertsapi/views.py
index c984dc8..71a2a77 100644
--- a/src/service/clmcservice/alertsapi/views.py
+++ b/src/service/clmcservice/alertsapi/views.py
@@ -98,6 +98,8 @@ class AlertsConfigurationAPI(object):
         """
 
         kapacitor_host, kapacitor_port = self.request.registry.settings['kapacitor_host'], self.request.registry.settings['kapacitor_port']
+        sfemc_fqdn, sfemc_port = self.request.registry.settings['sfemc_fqdn'], self.request.registry.settings['sfemc_port']
+        fqdn_prefix = "http://{0}:{1}/sfemc/event".format(sfemc_fqdn, sfemc_port)
 
         # fetch the URL parameters
         sfc_id, sfc_instance_id = self.request.matchdict["sfc_id"], self.request.matchdict["sfc_instance_id"]
@@ -123,12 +125,17 @@ class AlertsConfigurationAPI(object):
                 policy_id = task_config["policy"]["value"]
                 trigger_id = task_config["eventID"]["value"]
 
+                kapacitor_handlers_relative_url = "/kapacitor/v1/alerts/topics/{0}/handlers".format(topic_id)
+                kapacitor_handlers_full_url = "http://{0}:{1}{2}".format(kapacitor_host, kapacitor_port, kapacitor_handlers_relative_url)
+                handlers = [handler_obj["options"]["url"] for handler_obj in get(kapacitor_handlers_full_url).json()["handlers"]]
+                handlers = list(map(lambda handler: SFEMC if handler.startswith(fqdn_prefix) else handler, handlers))
+
                 # add it to the list of alerts for this SFC instance
-                sfc_instance_tasks.append({"policy": policy_id, "trigger": trigger_id,
+                sfc_instance_tasks.append({"policy": policy_id, "trigger": trigger_id, "handlers": handlers,
                                            "task_identifier": task_id, "topic_identifier": topic_id,
                                            "task_api_endpoint": "/kapacitor/v1/tasks/{0}".format(task_id),
                                            "topic_api_endpoint": "/kapacitor/v1/alerts/topics/{0}".format(topic_id),
-                                           "topic_handlers_api_endpoint": "/kapacitor/v1/alerts/topics/{0}/handlers".format(topic_id)})
+                                           "topic_handlers_api_endpoint": kapacitor_handlers_relative_url})
 
         return sfc_instance_tasks
 
@@ -144,6 +151,7 @@ class AlertsConfigurationAPI(object):
 
         kapacitor_host, kapacitor_port = self.request.registry.settings['kapacitor_host'], self.request.registry.settings['kapacitor_port']
         sfemc_fqdn, sfemc_port = self.request.registry.settings['sfemc_fqdn'], self.request.registry.settings['sfemc_port']
+        fqdn_prefix = "http://{0}:{1}/sfemc/event".format(sfemc_fqdn, sfemc_port)
 
         # since this is not a POST request, need to fetch the alert specification file from request.params, rather than request.POST
         alert_spec_reference = self.request.params.get('alert-spec')
@@ -185,7 +193,7 @@ class AlertsConfigurationAPI(object):
                 for handler in http_handlers:
 
                     original_http_handler_url = handler["options"]["url"]
-                    if original_http_handler_url.startswith("http://{0}:{1}/".format(sfemc_fqdn, sfemc_port)):
+                    if original_http_handler_url.startswith(fqdn_prefix):
                         original_http_handler_url = SFEMC
 
                     handler_id = handler["id"]
diff --git a/src/test/clmctest/alerts/test_alerts.py b/src/test/clmctest/alerts/test_alerts.py
index db664a6..808ab25 100644
--- a/src/test/clmctest/alerts/test_alerts.py
+++ b/src/test/clmctest/alerts/test_alerts.py
@@ -133,23 +133,33 @@ class TestAlerts(object):
         assert response.status_code == 200
         clmc_service_response = response.json()
         clmc_service_response = sorted(clmc_service_response, key=lambda x: x["trigger"])  # sort by trigger so that the response can be compared to what's expected
+
+        # sort the handlers of returned alerts to ensure comparison order is correct
+        for alert in clmc_service_response:
+            alert["handlers"] = sorted(alert["handlers"])
+
+        # compare actual response with expected response
         assert clmc_service_response == [
             {"policy": "scale_nginx_policy", "trigger": "high_requests", "task_identifier": "46fb8800c8a5eeeb04b090d838d475df574a2e6d854b5d678fc981c096eb6c1b",
+             "handlers": ["http://172.40.231.200:9999/"],
              "topic_identifier": "46fb8800c8a5eeeb04b090d838d475df574a2e6d854b5d678fc981c096eb6c1b",
              "task_api_endpoint": "/kapacitor/v1/tasks/46fb8800c8a5eeeb04b090d838d475df574a2e6d854b5d678fc981c096eb6c1b",
              "topic_api_endpoint": "/kapacitor/v1/alerts/topics/46fb8800c8a5eeeb04b090d838d475df574a2e6d854b5d678fc981c096eb6c1b",
              "topic_handlers_api_endpoint": "/kapacitor/v1/alerts/topics/46fb8800c8a5eeeb04b090d838d475df574a2e6d854b5d678fc981c096eb6c1b/handlers"},
             {"policy": "scale_nginx_policy", "trigger": "increase_in_active_requests", "task_identifier": "7a9867f9270dba6635ac3760a3b70bc929f5bd0f3bf582e45d27fbd437f528ca",
+             "handlers": ["flame_sfemc", "http://172.40.231.200:9999/"],
              "topic_identifier": "7a9867f9270dba6635ac3760a3b70bc929f5bd0f3bf582e45d27fbd437f528ca",
              "task_api_endpoint": "/kapacitor/v1/tasks/7a9867f9270dba6635ac3760a3b70bc929f5bd0f3bf582e45d27fbd437f528ca",
              "topic_api_endpoint": "/kapacitor/v1/alerts/topics/7a9867f9270dba6635ac3760a3b70bc929f5bd0f3bf582e45d27fbd437f528ca",
              "topic_handlers_api_endpoint": "/kapacitor/v1/alerts/topics/7a9867f9270dba6635ac3760a3b70bc929f5bd0f3bf582e45d27fbd437f528ca/handlers"},
             {"policy": "scale_nginx_policy", "trigger": "increase_in_running_processes", "task_identifier": "f5edaeb27fb847116be749c3815d240cbf0d7ba79aee1959daf0b3445a70f2c8",
+             "handlers": ["flame_sfemc", "http://172.40.231.200:9999/"],
              "topic_identifier": "f5edaeb27fb847116be749c3815d240cbf0d7ba79aee1959daf0b3445a70f2c8",
              "task_api_endpoint": "/kapacitor/v1/tasks/f5edaeb27fb847116be749c3815d240cbf0d7ba79aee1959daf0b3445a70f2c8",
              "topic_api_endpoint": "/kapacitor/v1/alerts/topics/f5edaeb27fb847116be749c3815d240cbf0d7ba79aee1959daf0b3445a70f2c8",
              "topic_handlers_api_endpoint": "/kapacitor/v1/alerts/topics/f5edaeb27fb847116be749c3815d240cbf0d7ba79aee1959daf0b3445a70f2c8/handlers"},
             {"policy": "deadman_policy", "trigger": "no_measurements", "task_identifier": "f7dab6fd53001c812d44533d3bbb6ef45f0d1d39b9441bc3c60402ebda85d320",
+             "handlers": ["flame_sfemc", "http://172.40.231.200:9999/"],
              "topic_identifier": "f7dab6fd53001c812d44533d3bbb6ef45f0d1d39b9441bc3c60402ebda85d320",
              "task_api_endpoint": "/kapacitor/v1/tasks/f7dab6fd53001c812d44533d3bbb6ef45f0d1d39b9441bc3c60402ebda85d320",
              "topic_api_endpoint": "/kapacitor/v1/alerts/topics/f7dab6fd53001c812d44533d3bbb6ef45f0d1d39b9441bc3c60402ebda85d320",
-- 
GitLab