diff --git a/CHANGELOG.md b/CHANGELOG.md index 03a6ed7f..896e5472 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. - Add the MATTERMOST_ENABLED setting (#471) - Add the MSTEAMS_ENABLED setting (#471) - Add the OPSGENIE_ENABLED setting (#471) +- Add the PD_ENABLED setting (#471) ## Bug Fixes - Fix unwanted HTML escaping in SMS and WhatsApp notifications diff --git a/docker/.env b/docker/.env index 997e94b1..3cc181a6 100644 --- a/docker/.env +++ b/docker/.env @@ -28,6 +28,7 @@ MATRIX_USER_ID= MATTERMOST_ENABLED=True MSTEAMS_ENABLED=True OPSGENIE_ENABLED=True +PD_ENABLED=True PD_VENDOR_KEY= PING_BODY_LIMIT=10000 PING_EMAIL_DOMAIN=localhost diff --git a/hc/api/tests/test_notify.py b/hc/api/tests/test_notify.py index e0ac7eea..dd94a433 100644 --- a/hc/api/tests/test_notify.py +++ b/hc/api/tests/test_notify.py @@ -25,32 +25,6 @@ class NotifyTestCase(BaseTestCase): self.channel.save() self.channel.checks.add(self.check) - @patch("hc.api.transports.requests.request") - def test_pd(self, mock_post): - self._setup_data("pd", "123") - mock_post.return_value.status_code = 200 - - self.channel.notify(self.check) - assert Notification.objects.count() == 1 - - args, kwargs = mock_post.call_args - payload = kwargs["json"] - self.assertEqual(payload["event_type"], "trigger") - self.assertEqual(payload["service_key"], "123") - - @patch("hc.api.transports.requests.request") - def test_pd_complex(self, mock_post): - self._setup_data("pd", json.dumps({"service_key": "456"})) - mock_post.return_value.status_code = 200 - - self.channel.notify(self.check) - assert Notification.objects.count() == 1 - - args, kwargs = mock_post.call_args - payload = kwargs["json"] - self.assertEqual(payload["event_type"], "trigger") - self.assertEqual(payload["service_key"], "456") - @patch("hc.api.transports.requests.request") def test_pagertree(self, mock_post): self._setup_data("pagertree", "123") diff --git a/hc/api/tests/test_notify_pd.py b/hc/api/tests/test_notify_pd.py new file mode 100644 index 00000000..6b2cfdd7 --- /dev/null +++ b/hc/api/tests/test_notify_pd.py @@ -0,0 +1,59 @@ +# coding: utf-8 + +from datetime import timedelta as td +import json +from unittest.mock import patch + +from django.utils.timezone import now +from hc.api.models import Channel, Check, Notification +from hc.test import BaseTestCase +from django.test.utils import override_settings + + +class NotifyTestCase(BaseTestCase): + def _setup_data(self, value, status="down", email_verified=True): + self.check = Check(project=self.project) + self.check.status = status + self.check.last_ping = now() - td(minutes=61) + self.check.save() + + self.channel = Channel(project=self.project) + self.channel.kind = "pd" + self.channel.value = value + self.channel.email_verified = email_verified + self.channel.save() + self.channel.checks.add(self.check) + + @patch("hc.api.transports.requests.request") + def test_pd(self, mock_post): + self._setup_data("123") + mock_post.return_value.status_code = 200 + + self.channel.notify(self.check) + assert Notification.objects.count() == 1 + + args, kwargs = mock_post.call_args + payload = kwargs["json"] + self.assertEqual(payload["event_type"], "trigger") + self.assertEqual(payload["service_key"], "123") + + @patch("hc.api.transports.requests.request") + def test_pd_complex(self, mock_post): + self._setup_data(json.dumps({"service_key": "456"})) + mock_post.return_value.status_code = 200 + + self.channel.notify(self.check) + assert Notification.objects.count() == 1 + + args, kwargs = mock_post.call_args + payload = kwargs["json"] + self.assertEqual(payload["event_type"], "trigger") + self.assertEqual(payload["service_key"], "456") + + @override_settings(PD_ENABLED=False) + def test_it_requires_pd_enabled(self): + self._setup_data("123") + self.channel.notify(self.check) + + n = Notification.objects.get() + self.assertEqual(n.error, "PagerDuty notifications are not enabled.") diff --git a/hc/api/transports.py b/hc/api/transports.py index fa8b35e8..c0bda0ce 100644 --- a/hc/api/transports.py +++ b/hc/api/transports.py @@ -318,6 +318,9 @@ class PagerDuty(HttpTransport): URL = "https://events.pagerduty.com/generic/2010-04-15/create_event.json" def notify(self, check): + if not settings.PD_ENABLED: + return "PagerDuty notifications are not enabled." + description = tmpl("pd_description.html", check=check) payload = { "service_key": self.channel.pd_service_key, diff --git a/hc/front/tests/test_add_pd.py b/hc/front/tests/test_add_pd.py index 35a10c9b..fda6388d 100644 --- a/hc/front/tests/test_add_pd.py +++ b/hc/front/tests/test_add_pd.py @@ -1,3 +1,4 @@ +from django.test.utils import override_settings from hc.api.models import Channel from hc.test import BaseTestCase @@ -40,3 +41,9 @@ class AddPdTestCase(BaseTestCase): self.client.login(username="bob@example.org", password="password") r = self.client.get(self.url) self.assertEqual(r.status_code, 403) + + @override_settings(PD_ENABLED=False) + def test_it_handles_disabled_integration(self): + self.client.login(username="alice@example.org", password="password") + r = self.client.get(self.url) + self.assertEqual(r.status_code, 404) diff --git a/hc/front/tests/test_add_pdc.py b/hc/front/tests/test_add_pdc.py index 937a4b82..73de6cd7 100644 --- a/hc/front/tests/test_add_pdc.py +++ b/hc/front/tests/test_add_pdc.py @@ -31,6 +31,13 @@ class AddPdConnectTestCase(BaseTestCase): r = self.client.get(self.url) self.assertEqual(r.status_code, 404) + @override_settings(PD_ENABLED=False) + def test_it_requires_pd_enabled(self): + self.client.login(username="alice@example.org", password="password") + + r = self.client.get(self.url) + self.assertEqual(r.status_code, 404) + def test_it_requires_rw_access(self): self.bobs_membership.rw = False self.bobs_membership.save() diff --git a/hc/front/tests/test_add_pdc_complete.py b/hc/front/tests/test_add_pdc_complete.py index 9fa7f598..4926470b 100644 --- a/hc/front/tests/test_add_pdc_complete.py +++ b/hc/front/tests/test_add_pdc_complete.py @@ -25,6 +25,13 @@ class AddPdcCompleteTestCase(BaseTestCase): r = self.client.get(self.url) self.assertEqual(r.status_code, 404) + @override_settings(PD_ENABLED=False) + def test_it_requires_pd_enabled(self): + self.client.login(username="alice@example.org", password="password") + + r = self.client.get(self.url) + self.assertEqual(r.status_code, 404) + def test_it_requires_rw_access(self): self.bobs_membership.rw = False self.bobs_membership.save() diff --git a/hc/front/views.py b/hc/front/views.py index e6d948dd..da6c54fb 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -298,6 +298,7 @@ def index(request): "enable_mattermost": settings.MATTERMOST_ENABLED is True, "enable_msteams": settings.MSTEAMS_ENABLED is True, "enable_opsgenie": settings.OPSGENIE_ENABLED is True, + "enable_pd": settings.PD_ENABLED is True, "enable_pdc": settings.PD_VENDOR_KEY is not None, "enable_pushbullet": settings.PUSHBULLET_CLIENT_ID is not None, "enable_pushover": settings.PUSHOVER_API_TOKEN is not None, @@ -769,6 +770,7 @@ def channels(request, code): "enable_mattermost": settings.MATTERMOST_ENABLED is True, "enable_msteams": settings.MSTEAMS_ENABLED is True, "enable_opsgenie": settings.OPSGENIE_ENABLED is True, + "enable_pd": settings.PD_ENABLED is True, "enable_pdc": settings.PD_VENDOR_KEY is not None, "enable_pushbullet": settings.PUSHBULLET_CLIENT_ID is not None, "enable_pushover": settings.PUSHOVER_API_TOKEN is not None, @@ -1027,6 +1029,7 @@ def add_shell(request, code): return render(request, "integrations/add_shell.html", ctx) +@require_setting("PD_ENABLED") @login_required def add_pd(request, code): project = _get_rw_project_for_user(request, code) @@ -1047,12 +1050,14 @@ def add_pd(request, code): return render(request, "integrations/add_pd.html", ctx) +@require_setting("PD_ENABLED") @require_setting("PD_VENDOR_KEY") def pdc_help(request): ctx = {"page": "channels"} return render(request, "integrations/add_pdc.html", ctx) +@require_setting("PD_ENABLED") @require_setting("PD_VENDOR_KEY") @login_required def add_pdc(request, code): @@ -1071,6 +1076,7 @@ def add_pdc(request, code): return render(request, "integrations/add_pdc.html", ctx) +@require_setting("PD_ENABLED") @require_setting("PD_VENDOR_KEY") @login_required def add_pdc_complete(request, code, state): diff --git a/hc/settings.py b/hc/settings.py index 20876cdc..3ba0e986 100644 --- a/hc/settings.py +++ b/hc/settings.py @@ -209,6 +209,7 @@ MSTEAMS_ENABLED = envbool("MSTEAMS_ENABLED", "True") OPSGENIE_ENABLED = envbool("OPSGENIE_ENABLED", "True") # PagerDuty +PD_ENABLED = envbool("PD_ENABLED", "True") PD_VENDOR_KEY = os.getenv("PD_VENDOR_KEY") # Pushover integration diff --git a/templates/docs/self_hosted_configuration.html b/templates/docs/self_hosted_configuration.html index cbed0a4b..2935e1cd 100644 --- a/templates/docs/self_hosted_configuration.html +++ b/templates/docs/self_hosted_configuration.html @@ -149,10 +149,12 @@ integration.
OPSGENIE_ENABLED
Default: True
A boolean that turns on/off the Opsgenie integration. Enabled by default.
+PD_ENABLED
Default: True
A boolean that turns on/off the Pagerduty integration. Enabled by default.
PD_VENDOR_KEY
Default: None
PagerDuty vendor key, -required by the PagerDuty integration.
+PagerDuty vendor key, used by the PagerDuty integration.
PING_BODY_LIMIT
Default: 10000
The upper size limit in bytes for logged ping request bodies. diff --git a/templates/docs/self_hosted_configuration.md b/templates/docs/self_hosted_configuration.md index 455cd4fe..6c24c070 100644 --- a/templates/docs/self_hosted_configuration.md +++ b/templates/docs/self_hosted_configuration.md @@ -248,12 +248,17 @@ Default: `True` A boolean that turns on/off the Opsgenie integration. Enabled by default. +## `PD_ENABLED` {: #PD_ENABLED } + +Default: `True` + +A boolean that turns on/off the PagerDuty integration. Enabled by default. + ## `PD_VENDOR_KEY` {: #PD_VENDOR_KEY } Default: `None` -[PagerDuty](https://www.pagerduty.com/) vendor key, -required by the PagerDuty integration. +[PagerDuty](https://www.pagerduty.com/) vendor key, used by the PagerDuty integration. ## `PING_BODY_LIMIT` {: #PING_BODY_LIMIT } diff --git a/templates/front/channels.html b/templates/front/channels.html index 47a25e50..ff6f165b 100644 --- a/templates/front/channels.html +++ b/templates/front/channels.html @@ -298,6 +298,7 @@ {% endif %} + {% if enable_pd %}