forked from GithubBackups/healthchecks
Alternate flow for setting up PagerDuty integration, without using PD Connect
This commit is contained in:
parent
d06721ab58
commit
f6d36b3491
@ -175,3 +175,8 @@ class AddMatrixForm(forms.Form):
|
|||||||
class AddAppriseForm(forms.Form):
|
class AddAppriseForm(forms.Form):
|
||||||
error_css_class = "has-error"
|
error_css_class = "has-error"
|
||||||
url = forms.CharField(max_length=512)
|
url = forms.CharField(max_length=512)
|
||||||
|
|
||||||
|
|
||||||
|
class AddPdForm(forms.Form):
|
||||||
|
error_css_class = "has-error"
|
||||||
|
value = forms.CharField(max_length=32)
|
||||||
|
32
hc/front/tests/test_add_pd.py
Normal file
32
hc/front/tests/test_add_pd.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from hc.api.models import Channel
|
||||||
|
from hc.test import BaseTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class AddPdTestCase(BaseTestCase):
|
||||||
|
url = "/integrations/add_pd/"
|
||||||
|
|
||||||
|
def test_instructions_work(self):
|
||||||
|
self.client.login(username="alice@example.org", password="password")
|
||||||
|
r = self.client.get(self.url)
|
||||||
|
self.assertContains(r, "Paste the Integration Key down below")
|
||||||
|
|
||||||
|
def test_it_works(self):
|
||||||
|
# Integration key is 32 characters long
|
||||||
|
form = {"value": "12345678901234567890123456789012"}
|
||||||
|
|
||||||
|
self.client.login(username="alice@example.org", password="password")
|
||||||
|
r = self.client.post(self.url, form)
|
||||||
|
self.assertRedirects(r, "/integrations/")
|
||||||
|
|
||||||
|
c = Channel.objects.get()
|
||||||
|
self.assertEqual(c.kind, "pd")
|
||||||
|
self.assertEqual(c.value, "12345678901234567890123456789012")
|
||||||
|
|
||||||
|
def test_it_trims_whitespace(self):
|
||||||
|
form = {"value": " 123456 "}
|
||||||
|
|
||||||
|
self.client.login(username="alice@example.org", password="password")
|
||||||
|
self.client.post(self.url, form)
|
||||||
|
|
||||||
|
c = Channel.objects.get()
|
||||||
|
self.assertEqual(c.value, "123456")
|
@ -27,6 +27,7 @@ channel_urls = [
|
|||||||
path("add_email/", views.add_email, name="hc-add-email"),
|
path("add_email/", views.add_email, name="hc-add-email"),
|
||||||
path("add_webhook/", views.add_webhook, name="hc-add-webhook"),
|
path("add_webhook/", views.add_webhook, name="hc-add-webhook"),
|
||||||
path("add_shell/", views.add_shell, name="hc-add-shell"),
|
path("add_shell/", views.add_shell, name="hc-add-shell"),
|
||||||
|
path("add_pd/", views.add_pd, name="hc-add-pd"),
|
||||||
path("add_pdc/", views.add_pdc, name="hc-add-pdc"),
|
path("add_pdc/", views.add_pdc, name="hc-add-pdc"),
|
||||||
path("add_pdc/<str:state>/", views.add_pdc, name="hc-add-pdc-state"),
|
path("add_pdc/<str:state>/", views.add_pdc, name="hc-add-pdc-state"),
|
||||||
path("add_pagertree/", views.add_pagertree, name="hc-add-pagertree"),
|
path("add_pagertree/", views.add_pagertree, name="hc-add-pagertree"),
|
||||||
|
@ -34,19 +34,20 @@ from hc.api.models import (
|
|||||||
)
|
)
|
||||||
from hc.api.transports import Telegram
|
from hc.api.transports import Telegram
|
||||||
from hc.front.forms import (
|
from hc.front.forms import (
|
||||||
|
AddAppriseForm,
|
||||||
|
AddEmailForm,
|
||||||
|
AddMatrixForm,
|
||||||
|
AddOpsGenieForm,
|
||||||
|
AddPdForm,
|
||||||
|
AddShellForm,
|
||||||
|
AddSmsForm,
|
||||||
|
AddUrlForm,
|
||||||
AddWebhookForm,
|
AddWebhookForm,
|
||||||
|
ChannelNameForm,
|
||||||
|
CronForm,
|
||||||
|
EmailSettingsForm,
|
||||||
NameTagsForm,
|
NameTagsForm,
|
||||||
TimeoutForm,
|
TimeoutForm,
|
||||||
AddUrlForm,
|
|
||||||
AddEmailForm,
|
|
||||||
AddOpsGenieForm,
|
|
||||||
CronForm,
|
|
||||||
AddSmsForm,
|
|
||||||
ChannelNameForm,
|
|
||||||
EmailSettingsForm,
|
|
||||||
AddMatrixForm,
|
|
||||||
AddAppriseForm,
|
|
||||||
AddShellForm,
|
|
||||||
)
|
)
|
||||||
from hc.front.schemas import telegram_callback
|
from hc.front.schemas import telegram_callback
|
||||||
from hc.front.templatetags.hc_extras import num_down_title, down_title, sortchecks
|
from hc.front.templatetags.hc_extras import num_down_title, down_title, sortchecks
|
||||||
@ -252,7 +253,6 @@ def index(request):
|
|||||||
"enable_telegram": settings.TELEGRAM_TOKEN is not None,
|
"enable_telegram": settings.TELEGRAM_TOKEN is not None,
|
||||||
"enable_sms": settings.TWILIO_AUTH is not None,
|
"enable_sms": settings.TWILIO_AUTH is not None,
|
||||||
"enable_whatsapp": settings.TWILIO_USE_WHATSAPP,
|
"enable_whatsapp": settings.TWILIO_USE_WHATSAPP,
|
||||||
"enable_pd": settings.PD_VENDOR_KEY is not None,
|
|
||||||
"enable_trello": settings.TRELLO_APP_KEY is not None,
|
"enable_trello": settings.TRELLO_APP_KEY is not None,
|
||||||
"enable_matrix": settings.MATRIX_ACCESS_TOKEN is not None,
|
"enable_matrix": settings.MATRIX_ACCESS_TOKEN is not None,
|
||||||
"enable_apprise": settings.APPRISE_ENABLED is True,
|
"enable_apprise": settings.APPRISE_ENABLED is True,
|
||||||
@ -649,7 +649,7 @@ def channels(request):
|
|||||||
"enable_telegram": settings.TELEGRAM_TOKEN is not None,
|
"enable_telegram": settings.TELEGRAM_TOKEN is not None,
|
||||||
"enable_sms": settings.TWILIO_AUTH is not None,
|
"enable_sms": settings.TWILIO_AUTH is not None,
|
||||||
"enable_whatsapp": settings.TWILIO_USE_WHATSAPP,
|
"enable_whatsapp": settings.TWILIO_USE_WHATSAPP,
|
||||||
"enable_pd": settings.PD_VENDOR_KEY is not None,
|
"enable_pdc": settings.PD_VENDOR_KEY is not None,
|
||||||
"enable_trello": settings.TRELLO_APP_KEY is not None,
|
"enable_trello": settings.TRELLO_APP_KEY is not None,
|
||||||
"enable_matrix": settings.MATRIX_ACCESS_TOKEN is not None,
|
"enable_matrix": settings.MATRIX_ACCESS_TOKEN is not None,
|
||||||
"enable_apprise": settings.APPRISE_ENABLED is True,
|
"enable_apprise": settings.APPRISE_ENABLED is True,
|
||||||
@ -863,6 +863,24 @@ def _get_validated_code(request, session_key, key="code"):
|
|||||||
return request.GET.get(key)
|
return request.GET.get(key)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add_pd(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
form = AddPdForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
channel = Channel(project=request.project, kind="pd")
|
||||||
|
channel.value = form.cleaned_data["value"]
|
||||||
|
channel.save()
|
||||||
|
|
||||||
|
channel.assign_all_checks()
|
||||||
|
return redirect("hc-channels")
|
||||||
|
else:
|
||||||
|
form = AddPdForm()
|
||||||
|
|
||||||
|
ctx = {"page": "channels", "form": form}
|
||||||
|
return render(request, "integrations/add_pd.html", ctx)
|
||||||
|
|
||||||
|
|
||||||
def add_pdc(request, state=None):
|
def add_pdc(request, state=None):
|
||||||
if settings.PD_VENDOR_KEY is None:
|
if settings.PD_VENDOR_KEY is None:
|
||||||
raise Http404("pagerduty integration is not available")
|
raise Http404("pagerduty integration is not available")
|
||||||
|
BIN
static/img/integrations/setup_pd_s1.png
Normal file
BIN
static/img/integrations/setup_pd_s1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
BIN
static/img/integrations/setup_pd_s2.png
Normal file
BIN
static/img/integrations/setup_pd_s2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@ -251,7 +251,6 @@
|
|||||||
<a href="{% url 'hc-add-opsgenie' %}" class="btn btn-primary">Add Integration</a>
|
<a href="{% url 'hc-add-opsgenie' %}" class="btn btn-primary">Add Integration</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{% if enable_pd %}
|
|
||||||
<li>
|
<li>
|
||||||
<img src="{% static 'img/integrations/pd.png' %}"
|
<img src="{% static 'img/integrations/pd.png' %}"
|
||||||
class="icon" alt="PagerDuty icon" />
|
class="icon" alt="PagerDuty icon" />
|
||||||
@ -259,9 +258,12 @@
|
|||||||
<h2>PagerDuty</h2>
|
<h2>PagerDuty</h2>
|
||||||
<p>On-call scheduling, alerting, and incident tracking.</p>
|
<p>On-call scheduling, alerting, and incident tracking.</p>
|
||||||
|
|
||||||
<a href="{% url 'hc-add-pdc' %}" class="btn btn-primary">Add Integration</a>
|
{% if enable_pdc %}
|
||||||
|
<a href="{% url 'hc-add-pdc' %}" class="btn btn-primary">Add Integration</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url 'hc-add-pd' %}" class="btn btn-primary">Add Integration</a>
|
||||||
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<img src="{% static 'img/integrations/pagerteam.png' %}"
|
<img src="{% static 'img/integrations/pagerteam.png' %}"
|
||||||
|
@ -378,14 +378,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if enable_pd %}
|
|
||||||
<div class="col-md-2 col-sm-4 col-xs-6">
|
<div class="col-md-2 col-sm-4 col-xs-6">
|
||||||
<div class="integration">
|
<div class="integration">
|
||||||
<img src="{% static 'img/integrations/pd.png' %}" class="icon" alt="" />
|
<img src="{% static 'img/integrations/pd.png' %}" class="icon" alt="" />
|
||||||
<h3>PagerDuty<br><small>Incident Management</small></h3>
|
<h3>PagerDuty<br><small>Incident Management</small></h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="col-md-2 col-sm-4 col-xs-6">
|
<div class="col-md-2 col-sm-4 col-xs-6">
|
||||||
<div class="integration">
|
<div class="integration">
|
||||||
|
94
templates/integrations/add_pd.html
Normal file
94
templates/integrations/add_pd.html
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load compress humanize staticfiles hc_extras %}
|
||||||
|
|
||||||
|
{% block title %}Add PagerDuty - {% site_name %}{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h1>PagerDuty</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If your team uses <a href="https://www.pagerduty.com/">PagerDuty</a>,
|
||||||
|
you can set up {% site_name %} to create a PagerDuty incident
|
||||||
|
when a check goes down, and resolve it when a check goes back up.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Setup Guide</h2>
|
||||||
|
<div class="row ai-step">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<span class="step-no">1</span>
|
||||||
|
<p>
|
||||||
|
Log into your PagerDuty account,
|
||||||
|
go to <strong>Configuration > Services</strong>,
|
||||||
|
and click on <strong>New Service</strong>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Give it a descriptive name, and
|
||||||
|
for Integration Type select
|
||||||
|
<strong>Use our API directly</strong>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<img
|
||||||
|
class="ai-guide-screenshot"
|
||||||
|
alt="Screenshot"
|
||||||
|
src="{% static 'img/integrations/setup_pd_s1.png' %}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row ai-step">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<span class="step-no">2</span>
|
||||||
|
After adding the new service, take note of its
|
||||||
|
<strong>Integration Key</strong>, a long string
|
||||||
|
of letters and digits.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<img
|
||||||
|
class="ai-guide-screenshot"
|
||||||
|
alt="Screenshot"
|
||||||
|
src="{% static 'img/integrations/setup_pd_s2.png' %}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row ai-step">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<span class="step-no">3</span>
|
||||||
|
<p>Paste the Integration Key down below. Save the integration, and it's done!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Integration Settings</h2>
|
||||||
|
|
||||||
|
<form method="post" class="form-horizontal" action="{% url 'hc-add-pd' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="form-group {{ form.value.css_classes }}">
|
||||||
|
<label for="api-key" class="col-sm-2 control-label">Integration Key</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input
|
||||||
|
id="api-key"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
name="value"
|
||||||
|
placeholder=""
|
||||||
|
value="{{ form.value.value|default:"" }}">
|
||||||
|
|
||||||
|
{% if form.value.errors %}
|
||||||
|
<div class="help-block">
|
||||||
|
{{ form.value.errors|join:"" }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button type="submit" class="btn btn-primary">Save Integration</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user