From b290c45ac95a9063cb9d954b51beba2b1c64deda Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Fri, 10 Apr 2020 08:49:56 -0400 Subject: [PATCH 1/9] Test first: Test that adding a new sensor (through the UI by submitting a form) add new sensor panel to the grafana dashboard). --- mercury/tests/test_grafana.py | 60 +++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/mercury/tests/test_grafana.py b/mercury/tests/test_grafana.py index 99eee0ce..354883a9 100644 --- a/mercury/tests/test_grafana.py +++ b/mercury/tests/test_grafana.py @@ -44,6 +44,16 @@ class TestGrafana(TestCase): "right_gust": {"unit": "km/h", "format": "float"}, } + test_type_object_name = "test-sensor-object" + test_sensor = {"name": "wind speed sensor", "type_id": test_type_object_name} + demo_sensor_type = { + "type-name": "fuel level", + "processing formula": 0, + "field-names": ["test-field-1", "test-field-2"], + "data-types": ["test-data-type-1", "test-data-type-2"], + "units": ["test-unit-1", "test-unit-2"], + } + test_event_data = { "name": "Sunny Day Test Drive", "date": datetime.datetime(2020, 2, 2, 20, 21, 22), @@ -72,6 +82,7 @@ def create_gfconfig(self): config.save() return config + # Returns event def create_venue_and_event(self, event_name): venue = AGVenue.objects.create( name=self.test_venue_data["name"], @@ -327,6 +338,55 @@ def test_add_multiple_panels(self): name = "".join([self.test_sensor_name, str(i)]) self.assertTrue(dashboard_info["dashboard"]["panels"][i]["title"] == name) + def test_add_sensor_creates_panel_in_dashboard(self): + # Create a dashboard, confirm it was created and retrieve its UID + dashboard = self.grafana.create_dashboard(self.event_name) + self.assertTrue(dashboard) + + # Create an event + # self.create_venue_and_event(self.event_name) + + sensor_type = AGSensorType.objects.create( + name=self.test_sensor_type, + processing_formula=0, + format=self.test_sensor_format, + ) + sensor_type.save() + + # POST sensor data + response = self.client.post( + reverse(self.sensor_url), + data={ + "submit_new_sensor": "", + "sensor-name": self.test_sensor["name"], + "select-sensor-type": self.test_sensor_type, + }, + ) + + """# POST sensor data + self.client.post( + reverse(self.sensor_url), + data={ + "submit": "", + "type-name": self.demo_sensor_type["type-name"], + "field-names": self.demo_sensor_type["field-names"], + "data-types": self.demo_sensor_type["data-types"], + "units": self.demo_sensor_type["units"], + }, + )""" + + # Fetch the dashboard again + dashboard = self.grafana.get_dashboard_by_name(dashboard["slug"]) + self.assertTrue(dashboard) + + # Confirm that a panel was added to the dashboard with the expected title + self.assertTrue(dashboard) + self.assertTrue(dashboard["dashboard"]) + self.assertTrue(dashboard["dashboard"]["panels"]) + self.assertTrue(len(dashboard["dashboard"]["panels"]) == 1) + self.assertTrue(dashboard["dashboard"]["panels"][0]["title"] == + self.test_sensor_name) + def test_add_panel_fail_no_dashboard_exists_for_event(self): # Create an event From 8a619ffb6bf6c6038efd301bcbdbd3ecfbf77bd2 Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Fri, 10 Apr 2020 10:41:03 -0400 Subject: [PATCH 2/9] Add sensor panel to each existing GFConfig's dashboard, not just the first GFConfig. --- mercury/views/sensor.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index ab416d54..01870063 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -253,6 +253,9 @@ def post(self, request, *args, **kwargs): sensor_types = ( AGSensorType.objects.all() ) # for when we return context later + + sensors = AGSensor.objects.all() + if valid: new_sensor = AGSensor.objects.create( name=sensor_name, type_id=sensor_type @@ -261,33 +264,32 @@ def post(self, request, *args, **kwargs): # Add a Sensor panel to the Active Event - # Check that Grafana is already configured - # and that an Active Event exists - # Note: THIS IS A PLACEHOLDER - waiting to decide # how to implement Current GFConfig - gf_configs = GFConfig.objects.filter(gf_current=True) + gfconfigs = GFConfig.objects.all() # Note: THIS IS A PLACEHOLDER - waiting to decide # how to implement Active Event active_events = AGEvent.objects.all() - if len(gf_configs) > 0 and len(active_events) > 0: - gf_config = gf_configs.first() + # Only add panel to active event + if len(active_events) > 0: active_event = active_events.first() - # Grafana instance using current GFConfig - grafana = Grafana(gf_config) + # Add panel to each grafana instance + for gfconfig in gfconfigs: - # Add the Sensor Panel to the Active Event's dashboard - try: - grafana.add_panel(new_sensor, active_event) - except ValueError as error: - messages.error( - request, f"Failed to add panel to active dashboard: {error}" - ) + # Grafana instance using current GFConfig + grafana = Grafana(gfconfig) + + # Add the Sensor Panel to the Active Event's dashboard + try: + grafana.add_panel(new_sensor, active_event) + except ValueError as error: + messages.error( + request, f"Failed to add panel to active dashboard: {error}" + ) - sensors = AGSensor.objects.all() context = {"sensors": sensors, "sensor_types": sensor_types} else: sensors = AGSensor.objects.all() From e750e0aed7635ce9a43a873ce17c7285091923b0 Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Fri, 10 Apr 2020 10:56:36 -0400 Subject: [PATCH 3/9] REFACTOR: Code which was being reused in several places to reformat strings to convert to lowercase and remove spaces (for Grafana) is now consolidated in one method. All previous code reuses were replaced with calls to the new method. --- mercury/grafanaAPI/grafana_api.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/mercury/grafanaAPI/grafana_api.py b/mercury/grafanaAPI/grafana_api.py index 0ca2adb6..e281b694 100644 --- a/mercury/grafanaAPI/grafana_api.py +++ b/mercury/grafanaAPI/grafana_api.py @@ -57,6 +57,14 @@ def __init__(self, gf_config=None): self.base_panel_width = 15 self.base_panel_height = 12 + def create_safe_string(self, input): + """ + Reformats the input string to be lowercase and with spaces replaced by '-'. + :param input: string + :return: reformatted string + """ + return input.strip().lower().replace(" ","-") + def generate_random_string(self, length): """ Generates a random string of letters of given length. @@ -107,8 +115,10 @@ def get_dashboard_by_name(self, event_name): """ # If there are spaces in the name, the GF API will replace them with dashes # to generate the "slug". A slug can be used to query the API. + formatted_event_name = self.create_safe_string(event_name) + endpoint = os.path.join( - self.hostname, "api/dashboards/db", event_name.lower().replace(" ", "-") + self.hostname, "api/dashboards/db", formatted_event_name ) response = requests.get(url=endpoint, auth=("api_key", self.api_token)) @@ -118,9 +128,9 @@ def get_dashboard_by_name(self, event_name): return None def get_dashboard_url_by_name(self, name): - name = name.strip().lower().replace(" ", "-") + search_name = self.create_safe_string(name) - dashboard = self.get_dashboard_by_name(name) + dashboard = self.get_dashboard_by_name(search_name) if dashboard: endpoint = dashboard["meta"]["url"].strip("/") url = os.path.join(self.hostname, endpoint) @@ -270,8 +280,9 @@ def delete_dashboard(self, uid): return False def delete_dashboard_by_name(self, name): + search_name = self.create_safe_string(name) endpoint = os.path.join( - self.hostname, "api/dashboards/db", name.lower().replace(" ", "-") + self.hostname, "api/dashboards/db", search_name ) response = requests.get(url=endpoint, auth=("api_key", self.api_token)) From c0c3abaee0f7c6772bcd263ec48ad6bcb4c88739 Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Fri, 10 Apr 2020 11:43:25 -0400 Subject: [PATCH 4/9] Fix test test_add_sensor_creates_panel_in_dashboard to check for the correct expected sensor name. --- mercury/tests/test_grafana.py | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/mercury/tests/test_grafana.py b/mercury/tests/test_grafana.py index 354883a9..3e76cf5b 100644 --- a/mercury/tests/test_grafana.py +++ b/mercury/tests/test_grafana.py @@ -44,16 +44,6 @@ class TestGrafana(TestCase): "right_gust": {"unit": "km/h", "format": "float"}, } - test_type_object_name = "test-sensor-object" - test_sensor = {"name": "wind speed sensor", "type_id": test_type_object_name} - demo_sensor_type = { - "type-name": "fuel level", - "processing formula": 0, - "field-names": ["test-field-1", "test-field-2"], - "data-types": ["test-data-type-1", "test-data-type-2"], - "units": ["test-unit-1", "test-unit-2"], - } - test_event_data = { "name": "Sunny Day Test Drive", "date": datetime.datetime(2020, 2, 2, 20, 21, 22), @@ -344,7 +334,7 @@ def test_add_sensor_creates_panel_in_dashboard(self): self.assertTrue(dashboard) # Create an event - # self.create_venue_and_event(self.event_name) + self.create_venue_and_event(self.event_name) sensor_type = AGSensorType.objects.create( name=self.test_sensor_type, @@ -358,23 +348,11 @@ def test_add_sensor_creates_panel_in_dashboard(self): reverse(self.sensor_url), data={ "submit_new_sensor": "", - "sensor-name": self.test_sensor["name"], + "sensor-name": self.test_sensor_name, "select-sensor-type": self.test_sensor_type, }, ) - """# POST sensor data - self.client.post( - reverse(self.sensor_url), - data={ - "submit": "", - "type-name": self.demo_sensor_type["type-name"], - "field-names": self.demo_sensor_type["field-names"], - "data-types": self.demo_sensor_type["data-types"], - "units": self.demo_sensor_type["units"], - }, - )""" - # Fetch the dashboard again dashboard = self.grafana.get_dashboard_by_name(dashboard["slug"]) self.assertTrue(dashboard) @@ -384,8 +362,11 @@ def test_add_sensor_creates_panel_in_dashboard(self): self.assertTrue(dashboard["dashboard"]) self.assertTrue(dashboard["dashboard"]["panels"]) self.assertTrue(len(dashboard["dashboard"]["panels"]) == 1) - self.assertTrue(dashboard["dashboard"]["panels"][0]["title"] == - self.test_sensor_name) + + # Note: converting test_sensor_name to lowercase because currently + # sensor names are automatically capitalized when they are created + self.assertEquals(dashboard["dashboard"]["panels"][0]["title"], + self.test_sensor_name.lower()) def test_add_panel_fail_no_dashboard_exists_for_event(self): From df194de64460c84109022edd2ba7c5f014e8fd15 Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Fri, 10 Apr 2020 11:44:14 -0400 Subject: [PATCH 5/9] Black and flake8. --- mercury/grafanaAPI/grafana_api.py | 6 ++---- mercury/tests/test_grafana.py | 7 ++++--- mercury/views/sensor.py | 3 ++- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mercury/grafanaAPI/grafana_api.py b/mercury/grafanaAPI/grafana_api.py index e281b694..783152f1 100644 --- a/mercury/grafanaAPI/grafana_api.py +++ b/mercury/grafanaAPI/grafana_api.py @@ -63,7 +63,7 @@ def create_safe_string(self, input): :param input: string :return: reformatted string """ - return input.strip().lower().replace(" ","-") + return input.strip().lower().replace(" ", "-") def generate_random_string(self, length): """ @@ -281,9 +281,7 @@ def delete_dashboard(self, uid): def delete_dashboard_by_name(self, name): search_name = self.create_safe_string(name) - endpoint = os.path.join( - self.hostname, "api/dashboards/db", search_name - ) + endpoint = os.path.join(self.hostname, "api/dashboards/db", search_name) response = requests.get(url=endpoint, auth=("api_key", self.api_token)) dashboard = response.json().get("dashboard") diff --git a/mercury/tests/test_grafana.py b/mercury/tests/test_grafana.py index 3e76cf5b..79d5050e 100644 --- a/mercury/tests/test_grafana.py +++ b/mercury/tests/test_grafana.py @@ -344,7 +344,7 @@ def test_add_sensor_creates_panel_in_dashboard(self): sensor_type.save() # POST sensor data - response = self.client.post( + self.client.post( reverse(self.sensor_url), data={ "submit_new_sensor": "", @@ -365,8 +365,9 @@ def test_add_sensor_creates_panel_in_dashboard(self): # Note: converting test_sensor_name to lowercase because currently # sensor names are automatically capitalized when they are created - self.assertEquals(dashboard["dashboard"]["panels"][0]["title"], - self.test_sensor_name.lower()) + self.assertEquals( + dashboard["dashboard"]["panels"][0]["title"], self.test_sensor_name.lower() + ) def test_add_panel_fail_no_dashboard_exists_for_event(self): diff --git a/mercury/views/sensor.py b/mercury/views/sensor.py index 01870063..254fec72 100644 --- a/mercury/views/sensor.py +++ b/mercury/views/sensor.py @@ -287,7 +287,8 @@ def post(self, request, *args, **kwargs): grafana.add_panel(new_sensor, active_event) except ValueError as error: messages.error( - request, f"Failed to add panel to active dashboard: {error}" + request, + f"Failed to add panel to active dashboard: {error}", ) context = {"sensors": sensors, "sensor_types": sensor_types} From e88aef9531f43922c5de3c5253576672b6370b17 Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Fri, 10 Apr 2020 13:40:07 -0400 Subject: [PATCH 6/9] Add a test for delete event. --- mercury/tests/test_event.py | 41 ++++++++++++++++++++++++++++++++++++- mercury/urls.py | 2 +- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/mercury/tests/test_event.py b/mercury/tests/test_event.py index 5c8fb742..2b770d95 100644 --- a/mercury/tests/test_event.py +++ b/mercury/tests/test_event.py @@ -1,6 +1,6 @@ from django.test import TestCase from django.urls import reverse -from mercury.models import EventCodeAccess +from mercury.models import EventCodeAccess, GFConfig from ag_data.models import AGEvent, AGVenue import datetime @@ -23,9 +23,34 @@ class TestEventView(TestCase): "longitude": 200, } + # Returns event + def create_venue_and_event(self, event_name): + venue = AGVenue.objects.create( + name=self.test_venue_data["name"], + description=self.test_venue_data["description"], + latitude=self.test_venue_data["latitude"], + longitude=self.test_venue_data["longitude"], + ) + venue.save() + + event = AGEvent.objects.create( + name=event_name, + date=self.test_event_data["date"], + description=self.test_event_data["description"], + venue_uuid=venue, + ) + event.save() + + return event + def setUp(self): self.login_url = "mercury:EventAccess" self.event_url = "mercury:events" + self.event_delete_url = "mercury:delete_event" + + # Create random event name + self.event_name = "test" + test_code = EventCodeAccess(event_code=self.TESTCODE, enabled=True) test_code.save() @@ -139,3 +164,17 @@ def test_create_event_with_correct_parameters(self): self.assertEqual(event.date, self.test_event_data["date"]) self.assertEqual(event.venue_uuid.uuid, venue.uuid) self.assertEqual(event.description, self.test_event_data["description"]) + + def test_delete_event(self): + # Create an event + event = self.create_venue_and_event(self.event_name) + + # Confirm that event was created + self.assertEquals(AGEvent.objects.all().count(), 1) + + # Delete the event + self.client.post(reverse(self.event_delete_url, kwargs={"event_uuid": + event.uuid})) + + # Confirm that event was deleted + self.assertEquals(AGEvent.objects.all().count(), 0) \ No newline at end of file diff --git a/mercury/urls.py b/mercury/urls.py index 2f7a09ee..2529a02e 100644 --- a/mercury/urls.py +++ b/mercury/urls.py @@ -36,7 +36,7 @@ name="update_type", ), path("events/", events.CreateEventsView.as_view(), name="events"), - path("events/delete/", events.delete_event), + path("events/delete/", events.delete_event, name="delete_event"), path("events/update/", events.update_event), path("events/updatevenue/", events.update_venue), path("events/export//csv", events.export_event), From 3378a29d7f4c1409e8c2eb0db34c0a90047687d3 Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Fri, 10 Apr 2020 13:52:27 -0400 Subject: [PATCH 7/9] Test first: Test that deleting an event deletes the grafana dashboard if there is no data, and keeps the dashboard if there is already data. --- mercury/tests/test_grafana.py | 43 ++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/mercury/tests/test_grafana.py b/mercury/tests/test_grafana.py index 79d5050e..3d1dc5d2 100644 --- a/mercury/tests/test_grafana.py +++ b/mercury/tests/test_grafana.py @@ -96,6 +96,7 @@ def setUp(self): self.login_url = "mercury:EventAccess" self.sensor_url = "mercury:sensor" self.event_url = "mercury:events" + self.event_delete_url = "mercury:delete_event" test_code = EventCodeAccess(event_code="testcode", enabled=True) test_code.save() # Login @@ -370,7 +371,6 @@ def test_add_sensor_creates_panel_in_dashboard(self): ) def test_add_panel_fail_no_dashboard_exists_for_event(self): - # Create an event event = self.create_venue_and_event(self.event_name) @@ -542,3 +542,44 @@ def test_create_event_creates_dashboard_with_panel(self): self.assertTrue( dashboard_info["dashboard"]["panels"][0]["title"] == sensor.name ) + + def test_delete_event_no_data_deletes_grafana_dashboard(self): + self.grafana.create_postgres_datasource(self.datasource_name) + + # Create a venue + venue = AGVenue.objects.create( + name=self.event_name, + description=self.test_venue_data["description"], + latitude=self.test_venue_data["latitude"], + longitude=self.test_venue_data["longitude"], + ) + venue.save() + + # Send a request to create an event (should trigger the creation of a + # grafana dashboard of the same name) + self.client.post( + reverse(self.event_url), + data={ + "submit-event": "", + "name": self.event_name, + "date": self.test_event_data["date"], + "description": self.test_event_data["description"], + "venue_uuid": venue.uuid, + }, + ) + + # Retrieve event object + event = AGEvent.objects.all().first() + + # Delete the event by posting to the delete view + self.client.post(reverse(self.event_delete_url, kwargs={"event_uuid": + event.uuid})) + # Try and retrieve the dashboard + dashboard = self.grafana.get_dashboard_by_name(self.event_name) + print(dashboard) + self.assertFalse(dashboard) + + # Generate sample data for the event, this should prevent the dashboard from + # being deleted + def test_delete_event_data_keeps_grafana_dashboard(self): + self.assertTrue(False) From 3b09c6480263e93aee1205ccc36e27a0fe5a994e Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Fri, 10 Apr 2020 14:28:24 -0400 Subject: [PATCH 8/9] Delete dashboard with event name from all GFConfigs when event is deleted from UI. Change tests because all event measurements are deleted when the event is deleted, so there is no need to check whether an event exists. --- mercury/templates/events.html | 4 ++++ mercury/tests/test_grafana.py | 12 +++++------- mercury/views/events.py | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/mercury/templates/events.html b/mercury/templates/events.html index 9e6a0fe2..935ade5f 100644 --- a/mercury/templates/events.html +++ b/mercury/templates/events.html @@ -124,6 +124,10 @@

All Events

{% else %}
There are no events to show.
{% endif %} + + {% for message in messages %} +

{{ message }}

+ {% endfor %} diff --git a/mercury/tests/test_grafana.py b/mercury/tests/test_grafana.py index 3d1dc5d2..439bd057 100644 --- a/mercury/tests/test_grafana.py +++ b/mercury/tests/test_grafana.py @@ -543,7 +543,7 @@ def test_create_event_creates_dashboard_with_panel(self): dashboard_info["dashboard"]["panels"][0]["title"] == sensor.name ) - def test_delete_event_no_data_deletes_grafana_dashboard(self): + def test_delete_event_deletes_grafana_dashboard(self): self.grafana.create_postgres_datasource(self.datasource_name) # Create a venue @@ -568,6 +568,9 @@ def test_delete_event_no_data_deletes_grafana_dashboard(self): }, ) + dashboard = self.grafana.get_dashboard_by_name(self.event_name) + self.assertTrue(dashboard) + # Retrieve event object event = AGEvent.objects.all().first() @@ -576,10 +579,5 @@ def test_delete_event_no_data_deletes_grafana_dashboard(self): event.uuid})) # Try and retrieve the dashboard dashboard = self.grafana.get_dashboard_by_name(self.event_name) - print(dashboard) - self.assertFalse(dashboard) - # Generate sample data for the event, this should prevent the dashboard from - # being deleted - def test_delete_event_data_keeps_grafana_dashboard(self): - self.assertTrue(False) + self.assertFalse(dashboard) \ No newline at end of file diff --git a/mercury/views/events.py b/mercury/views/events.py index 408d402d..b871f15d 100644 --- a/mercury/views/events.py +++ b/mercury/views/events.py @@ -46,7 +46,27 @@ def update_event(request, event_uuid=None): def delete_event(request, event_uuid=None): event_to_delete = AGEvent.objects.get(uuid=event_uuid) + + # delete any dashboards that exist for this event + gfconfigs = GFConfig.objects.all() + + # Add panel to each grafana instance + for gfconfig in gfconfigs: + + # Grafana instance using current GFConfig + grafana = Grafana(gfconfig) + + deleted = grafana.delete_dashboard_by_name(event_to_delete.name) + + if not deleted: + messages.error( + request, + f"Failed to delete Event dashboard from Grafana instance: " + f"{gfconfig.gf_host}" + ) + event_to_delete.delete() + return redirect("/events") From f3e9372a244792c02c5220e8f248c49bb3873769 Mon Sep 17 00:00:00 2001 From: Daisy Crego Date: Fri, 10 Apr 2020 14:50:17 -0400 Subject: [PATCH 9/9] Black and flake8. --- mercury/tests/test_event.py | 9 +++++---- mercury/tests/test_grafana.py | 7 ++++--- mercury/views/events.py | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/mercury/tests/test_event.py b/mercury/tests/test_event.py index 2b770d95..c5ab4534 100644 --- a/mercury/tests/test_event.py +++ b/mercury/tests/test_event.py @@ -1,6 +1,6 @@ from django.test import TestCase from django.urls import reverse -from mercury.models import EventCodeAccess, GFConfig +from mercury.models import EventCodeAccess from ag_data.models import AGEvent, AGVenue import datetime @@ -173,8 +173,9 @@ def test_delete_event(self): self.assertEquals(AGEvent.objects.all().count(), 1) # Delete the event - self.client.post(reverse(self.event_delete_url, kwargs={"event_uuid": - event.uuid})) + self.client.post( + reverse(self.event_delete_url, kwargs={"event_uuid": event.uuid}) + ) # Confirm that event was deleted - self.assertEquals(AGEvent.objects.all().count(), 0) \ No newline at end of file + self.assertEquals(AGEvent.objects.all().count(), 0) diff --git a/mercury/tests/test_grafana.py b/mercury/tests/test_grafana.py index 439bd057..63a11de2 100644 --- a/mercury/tests/test_grafana.py +++ b/mercury/tests/test_grafana.py @@ -575,9 +575,10 @@ def test_delete_event_deletes_grafana_dashboard(self): event = AGEvent.objects.all().first() # Delete the event by posting to the delete view - self.client.post(reverse(self.event_delete_url, kwargs={"event_uuid": - event.uuid})) + self.client.post( + reverse(self.event_delete_url, kwargs={"event_uuid": event.uuid}) + ) # Try and retrieve the dashboard dashboard = self.grafana.get_dashboard_by_name(self.event_name) - self.assertFalse(dashboard) \ No newline at end of file + self.assertFalse(dashboard) diff --git a/mercury/views/events.py b/mercury/views/events.py index b871f15d..db52e30a 100644 --- a/mercury/views/events.py +++ b/mercury/views/events.py @@ -62,7 +62,7 @@ def delete_event(request, event_uuid=None): messages.error( request, f"Failed to delete Event dashboard from Grafana instance: " - f"{gfconfig.gf_host}" + f"{gfconfig.gf_host}", ) event_to_delete.delete()