forked from GithubBackups/healthchecks
commit
31d4582dc0
18
hc/api/migrations/0059_auto_20190314_1744.py
Normal file
18
hc/api/migrations/0059_auto_20190314_1744.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.1.7 on 2019-03-14 17:44
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('api', '0058_auto_20190312_1716'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='channel',
|
||||||
|
name='kind',
|
||||||
|
field=models.CharField(choices=[('email', 'Email'), ('webhook', 'Webhook'), ('hipchat', 'HipChat'), ('slack', 'Slack'), ('pd', 'PagerDuty'), ('pagertree', 'PagerTree'), ('pagerteam', 'Pager Team'), ('po', 'Pushover'), ('pushbullet', 'Pushbullet'), ('opsgenie', 'OpsGenie'), ('victorops', 'VictorOps'), ('discord', 'Discord'), ('telegram', 'Telegram'), ('sms', 'SMS'), ('zendesk', 'Zendesk'), ('trello', 'Trello'), ('matrix', 'Matrix')], max_length=20),
|
||||||
|
),
|
||||||
|
]
|
@ -33,6 +33,7 @@ CHANNEL_KINDS = (("email", "Email"),
|
|||||||
("slack", "Slack"),
|
("slack", "Slack"),
|
||||||
("pd", "PagerDuty"),
|
("pd", "PagerDuty"),
|
||||||
("pagertree", "PagerTree"),
|
("pagertree", "PagerTree"),
|
||||||
|
("pagerteam", "Pager Team"),
|
||||||
("po", "Pushover"),
|
("po", "Pushover"),
|
||||||
("pushbullet", "Pushbullet"),
|
("pushbullet", "Pushbullet"),
|
||||||
("opsgenie", "OpsGenie"),
|
("opsgenie", "OpsGenie"),
|
||||||
@ -322,6 +323,8 @@ class Channel(models.Model):
|
|||||||
return transports.PagerDuty(self)
|
return transports.PagerDuty(self)
|
||||||
elif self.kind == "pagertree":
|
elif self.kind == "pagertree":
|
||||||
return transports.PagerTree(self)
|
return transports.PagerTree(self)
|
||||||
|
elif self.kind == "pagerteam":
|
||||||
|
return transports.PagerTeam(self)
|
||||||
elif self.kind == "victorops":
|
elif self.kind == "victorops":
|
||||||
return transports.VictorOps(self)
|
return transports.VictorOps(self)
|
||||||
elif self.kind == "pushbullet":
|
elif self.kind == "pushbullet":
|
||||||
|
@ -294,6 +294,18 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
payload = kwargs["json"]
|
payload = kwargs["json"]
|
||||||
self.assertEqual(payload["event_type"], "trigger")
|
self.assertEqual(payload["event_type"], "trigger")
|
||||||
|
|
||||||
|
@patch("hc.api.transports.requests.request")
|
||||||
|
def test_pagerteam(self, mock_post):
|
||||||
|
self._setup_data("pagerteam", "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")
|
||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
def test_slack(self, mock_post):
|
def test_slack(self, mock_post):
|
||||||
self._setup_data("slack", "123")
|
self._setup_data("slack", "123")
|
||||||
|
@ -269,6 +269,24 @@ class PagerTree(HttpTransport):
|
|||||||
|
|
||||||
return self.post(url, json=payload, headers=headers)
|
return self.post(url, json=payload, headers=headers)
|
||||||
|
|
||||||
|
class PagerTeam(HttpTransport):
|
||||||
|
def notify(self, check):
|
||||||
|
url = self.channel.value
|
||||||
|
headers = {
|
||||||
|
"Conent-Type": "application/json"
|
||||||
|
}
|
||||||
|
payload = {
|
||||||
|
"incident_key": str(check.code),
|
||||||
|
"event_type": "trigger" if check.status == "down" else "resolve",
|
||||||
|
"title": tmpl("pagerteam_title.html", check=check),
|
||||||
|
"description": tmpl("pagerteam_description.html", check=check),
|
||||||
|
"client": settings.SITE_NAME,
|
||||||
|
"client_url": settings.SITE_ROOT,
|
||||||
|
"tags": ",".join(check.tags_list())
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.post(url, json=payload, headers=headers)
|
||||||
|
|
||||||
|
|
||||||
class Pushbullet(HttpTransport):
|
class Pushbullet(HttpTransport):
|
||||||
def notify(self, check):
|
def notify(self, check):
|
||||||
|
30
hc/front/tests/test_add_pagerteam.py
Normal file
30
hc/front/tests/test_add_pagerteam.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from hc.api.models import Channel
|
||||||
|
from hc.test import BaseTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class AddPagerTeamTestCase(BaseTestCase):
|
||||||
|
url = "/integrations/add_pagerteam/"
|
||||||
|
|
||||||
|
def test_instructions_work(self):
|
||||||
|
self.client.login(username="alice@example.org", password="password")
|
||||||
|
r = self.client.get(self.url)
|
||||||
|
self.assertContains(r, "Pager Team")
|
||||||
|
|
||||||
|
def test_it_works(self):
|
||||||
|
form = {"value": "http://example.org"}
|
||||||
|
|
||||||
|
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, "pagerteam")
|
||||||
|
self.assertEqual(c.value, "http://example.org")
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|
||||||
|
def test_it_rejects_bad_url(self):
|
||||||
|
form = {"value": "not an URL"}
|
||||||
|
|
||||||
|
self.client.login(username="alice@example.org", password="password")
|
||||||
|
r = self.client.post(self.url, form)
|
||||||
|
self.assertContains(r, "Enter a valid URL")
|
@ -24,6 +24,7 @@ channel_urls = [
|
|||||||
path('add_pd/', views.add_pd, name="hc-add-pd"),
|
path('add_pd/', views.add_pd, name="hc-add-pd"),
|
||||||
path('add_pd/<str:state>/', views.add_pd, name="hc-add-pd-state"),
|
path('add_pd/<str:state>/', views.add_pd, name="hc-add-pd-state"),
|
||||||
path('add_pagertree/', views.add_pagertree, name="hc-add-pagertree"),
|
path('add_pagertree/', views.add_pagertree, name="hc-add-pagertree"),
|
||||||
|
path('add_pagerteam/', views.add_pagerteam, name="hc-add-pagerteam"),
|
||||||
path('add_slack/', views.add_slack, name="hc-add-slack"),
|
path('add_slack/', views.add_slack, name="hc-add-slack"),
|
||||||
path('add_slack_btn/', views.add_slack_btn, name="hc-add-slack-btn"),
|
path('add_slack_btn/', views.add_slack_btn, name="hc-add-slack-btn"),
|
||||||
path('add_pushbullet/', views.add_pushbullet, name="hc-add-pushbullet"),
|
path('add_pushbullet/', views.add_pushbullet, name="hc-add-pushbullet"),
|
||||||
|
@ -749,6 +749,23 @@ def add_pagertree(request):
|
|||||||
ctx = {"page": "channels", "form": form}
|
ctx = {"page": "channels", "form": form}
|
||||||
return render(request, "integrations/add_pagertree.html", ctx)
|
return render(request, "integrations/add_pagertree.html", ctx)
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def add_pagerteam(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
form = AddUrlForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
channel = Channel(project=request.project, kind="pagerteam")
|
||||||
|
channel.value = form.cleaned_data["value"]
|
||||||
|
channel.save()
|
||||||
|
|
||||||
|
channel.assign_all_checks()
|
||||||
|
return redirect("hc-channels")
|
||||||
|
else:
|
||||||
|
form = AddUrlForm()
|
||||||
|
|
||||||
|
ctx = {"page": "channels", "form": form}
|
||||||
|
return render(request, "integrations/add_pagerteam.html", ctx)
|
||||||
|
|
||||||
|
|
||||||
def add_slack(request):
|
def add_slack(request):
|
||||||
if not settings.SLACK_CLIENT_ID and not request.user.is_authenticated:
|
if not settings.SLACK_CLIENT_ID and not request.user.is_authenticated:
|
||||||
|
BIN
static/img/integrations/pagerteam.png
Normal file
BIN
static/img/integrations/pagerteam.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
BIN
static/img/integrations/setup_pagerteam_1.png
Normal file
BIN
static/img/integrations/setup_pagerteam_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 122 KiB |
@ -47,6 +47,8 @@
|
|||||||
PagerDuty account <span>{{ ch.pd_account }}</span>
|
PagerDuty account <span>{{ ch.pd_account }}</span>
|
||||||
{% elif ch.kind == "pagertree" %}
|
{% elif ch.kind == "pagertree" %}
|
||||||
PagerTree
|
PagerTree
|
||||||
|
{% elif ch.kind == "pagerteam" %}
|
||||||
|
Pager Team
|
||||||
{% elif ch.kind == "opsgenie" %}
|
{% elif ch.kind == "opsgenie" %}
|
||||||
OpsGenie
|
OpsGenie
|
||||||
{% elif ch.kind == "victorops" %}
|
{% elif ch.kind == "victorops" %}
|
||||||
@ -243,6 +245,15 @@
|
|||||||
|
|
||||||
<a href="{% url 'hc-add-victorops' %}" class="btn btn-primary">Add Integration</a>
|
<a href="{% url 'hc-add-victorops' %}" class="btn btn-primary">Add Integration</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<img src="{% static 'img/integrations/pagerteam.png' %}"
|
||||||
|
class="icon" alt="PagerTeam icon" />
|
||||||
|
|
||||||
|
<h2>Pager Team</h2>
|
||||||
|
<p>On-call scheduling, alerting, and incident tracking.</p>
|
||||||
|
|
||||||
|
<a href="{% url 'hc-add-pagerteam' %}" class="btn btn-primary">Add Integration</a>
|
||||||
|
</li>
|
||||||
{% if enable_discord %}
|
{% if enable_discord %}
|
||||||
<li>
|
<li>
|
||||||
<img src="{% static 'img/integrations/discord.png' %}"
|
<img src="{% static 'img/integrations/discord.png' %}"
|
||||||
|
@ -64,6 +64,8 @@
|
|||||||
Sent alert to PagerDuty
|
Sent alert to PagerDuty
|
||||||
{% elif event.channel.kind == "pagertree" %}
|
{% elif event.channel.kind == "pagertree" %}
|
||||||
Sent alert to PagerTree
|
Sent alert to PagerTree
|
||||||
|
{% elif event.channel.kind == "pagerteam" %}
|
||||||
|
Sent alert to Pager Team
|
||||||
{% elif event.channel.kind == "opsgenie" %}
|
{% elif event.channel.kind == "opsgenie" %}
|
||||||
Sent alert to OpsGenie
|
Sent alert to OpsGenie
|
||||||
{% elif event.channel.kind == "hipchat" %}
|
{% elif event.channel.kind == "hipchat" %}
|
||||||
|
@ -107,6 +107,8 @@
|
|||||||
Sent alert to PagerDuty
|
Sent alert to PagerDuty
|
||||||
{% elif event.channel.kind == "pagertree" %}
|
{% elif event.channel.kind == "pagertree" %}
|
||||||
Sent alert to PagerTree
|
Sent alert to PagerTree
|
||||||
|
{% elif event.channel.kind == "pagerteam" %}
|
||||||
|
Sent alert to Pager Team
|
||||||
{% elif event.channel.kind == "opsgenie" %}
|
{% elif event.channel.kind == "opsgenie" %}
|
||||||
Sent alert to OpsGenie
|
Sent alert to OpsGenie
|
||||||
{% elif event.channel.kind == "hipchat" %}
|
{% elif event.channel.kind == "hipchat" %}
|
||||||
|
@ -399,6 +399,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-2 col-sm-4 col-xs-6">
|
||||||
|
<div class="integration">
|
||||||
|
<img src="{% static 'img/integrations/pagerteam.png' %}" class="icon" alt="Pager Team icon" />
|
||||||
|
<h3>Pager Team <br><small>On-call rotations without limits</small></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if enable_trello %}
|
{% if enable_trello %}
|
||||||
<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">
|
||||||
|
71
templates/integrations/add_pagerteam.html
Normal file
71
templates/integrations/add_pagerteam.html
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load humanize static hc_extras %}
|
||||||
|
|
||||||
|
{% block title %}Add Pager Team - {% site_name %}{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h1>Pager Team</h1>
|
||||||
|
|
||||||
|
<p>You can integrate <a href="https://pagerteam.com">Pager Team</a>
|
||||||
|
with {% site_name %} to alert your on-call rotation whenever a check goes down.</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 Pager Team account, select the rotation you wish to add this integration to. Click the <strong>Copy Webhook</strong> button.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<img
|
||||||
|
class="ai-guide-screenshot"
|
||||||
|
alt="Click create integration button"
|
||||||
|
src="{% static 'img/integrations/setup_pagerteam_1.png' %}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row ai-step">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<span class="step-no">2</span>
|
||||||
|
<p>
|
||||||
|
Paste the <strong>Webhook URL</strong> below. Save the integration, and you are done!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Integration Settings</h2>
|
||||||
|
|
||||||
|
<form method="post" class="form-horizontal" action="{% url 'hc-add-pagerteam' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="form-group {{ form.value.css_classes }}">
|
||||||
|
<label for="post-url" class="col-sm-2 control-label">URL</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input
|
||||||
|
id="post-url"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
name="value"
|
||||||
|
placeholder="https://"
|
||||||
|
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 %}
|
5
templates/integrations/pagerteam_description.html
Normal file
5
templates/integrations/pagerteam_description.html
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{% load humanize %}
|
||||||
|
{{ check.name_then_code }} is {{ check.status|upper }}.
|
||||||
|
{% if check.status == "down" %}
|
||||||
|
Last ping was {{ check.last_ping|naturaltime }}.
|
||||||
|
{% endif %}
|
1
templates/integrations/pagerteam_title.html
Normal file
1
templates/integrations/pagerteam_title.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{ check.name_then_code }} is {{ check.status|upper }}
|
Loading…
x
Reference in New Issue
Block a user