From cb1eac50d98aa161c4ad7f888bd3be44cec030d1 Mon Sep 17 00:00:00 2001 From: Austin Date: Thu, 14 Dec 2017 11:10:08 -0800 Subject: [PATCH] Adds PagerTree Integration --- hc/api/models.py | 3 ++ hc/api/transports.py | 18 +++++++ hc/front/urls.py | 1 + static/img/integrations/pagertree.png | Bin 0 -> 4484 bytes templates/front/channels.html | 12 +++++ templates/front/log.html | 2 + templates/front/welcome.html | 7 +++ templates/integrations/add_pagertree.html | 46 ++++++++++++++++++ .../integrations/pagertree_description.html | 5 ++ templates/integrations/pagertree_title.html | 1 + 10 files changed, 95 insertions(+) create mode 100644 static/img/integrations/pagertree.png create mode 100644 templates/integrations/add_pagertree.html create mode 100644 templates/integrations/pagertree_description.html create mode 100644 templates/integrations/pagertree_title.html diff --git a/hc/api/models.py b/hc/api/models.py index 44cc2143..51c70e54 100644 --- a/hc/api/models.py +++ b/hc/api/models.py @@ -32,6 +32,7 @@ CHANNEL_KINDS = (("email", "Email"), ("hipchat", "HipChat"), ("slack", "Slack"), ("pd", "PagerDuty"), + ("pagertree", "PagerTree"), ("po", "Pushover"), ("pushbullet", "Pushbullet"), ("opsgenie", "OpsGenie"), @@ -260,6 +261,8 @@ class Channel(models.Model): return transports.HipChat(self) elif self.kind == "pd": return transports.PagerDuty(self) + elif self.kind == "pagertree": + return transports.PagerTree(self) elif self.kind == "victorops": return transports.VictorOps(self) elif self.kind == "pushbullet": diff --git a/hc/api/transports.py b/hc/api/transports.py index faf06cc8..4b1088d0 100644 --- a/hc/api/transports.py +++ b/hc/api/transports.py @@ -230,6 +230,24 @@ class PagerDuty(HttpTransport): return self.post(self.URL, json=payload) +class PagerTree(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("pagertree_title.html", check=check) + "description": tmpl("pagertree_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): def notify(self, check): diff --git a/hc/front/urls.py b/hc/front/urls.py index 4b209b57..5f5352df 100644 --- a/hc/front/urls.py +++ b/hc/front/urls.py @@ -17,6 +17,7 @@ channel_urls = [ url(r'^add_webhook/$', views.add_webhook, name="hc-add-webhook"), url(r'^add_pd/$', views.add_pd, name="hc-add-pd"), url(r'^add_pd/([\w]{12})/$', views.add_pd, name="hc-add-pd-state"), + url(r'^add_pagertree/$', views.add_pagertree, name="hc-add-pagertree"), url(r'^add_slack/$', views.add_slack, name="hc-add-slack"), url(r'^add_slack_btn/$', views.add_slack_btn, name="hc-add-slack-btn"), url(r'^add_hipchat/$', views.add_hipchat, name="hc-add-hipchat"), diff --git a/static/img/integrations/pagertree.png b/static/img/integrations/pagertree.png new file mode 100644 index 0000000000000000000000000000000000000000..380f95f1e08d8728e4f03639c6a8d050492f4f1d GIT binary patch literal 4484 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 literal 0 HcmV?d00001 diff --git a/templates/front/channels.html b/templates/front/channels.html index f6f98b71..097ea24d 100644 --- a/templates/front/channels.html +++ b/templates/front/channels.html @@ -50,6 +50,9 @@ {% endif %} service key {{ ch.pd_service_key }} + {% elif ch.kind == "pagertree" %} + URL + {{ ch.value }} {% elif ch.kind == "opsgenie" %} API key {{ ch.value }} @@ -227,6 +230,15 @@ Add Integration {% endif %} +
  • + PagerTree icon + +

    PagerTree

    +

    On-call. Simplified.

    + + Add Integration +
  • HipChat icon diff --git a/templates/front/log.html b/templates/front/log.html index 42422737..5f302e29 100644 --- a/templates/front/log.html +++ b/templates/front/log.html @@ -89,6 +89,8 @@ {% endif %} {% elif event.channel.kind == "pd" %} Sent alert to PagerDuty + {% elif event.channel.kind == "pagertree" %} + Sent alert to PagerTree {% elif event.channel.kind == "opsgenie" %} Sent alert to OpsGenie {% elif event.channel.kind == "hipchat" %} diff --git a/templates/front/welcome.html b/templates/front/welcome.html index 75b70e13..3cb0f625 100644 --- a/templates/front/welcome.html +++ b/templates/front/welcome.html @@ -319,6 +319,13 @@ {% endif %} + + + PagerTree icon + + Open and resolve incidents in PagerTree. + + HipChat icon diff --git a/templates/integrations/add_pagertree.html b/templates/integrations/add_pagertree.html new file mode 100644 index 00000000..f3d161c9 --- /dev/null +++ b/templates/integrations/add_pagertree.html @@ -0,0 +1,46 @@ +{% extends "base.html" %} +{% load compress humanize staticfiles hc_extras %} + +{% block title %}Add PagerTree - {% site_name %}{% endblock %} + + +{% block content %} +
    +
    +

    PagerTree

    + +

    If your team uses PagerTree, + you can set up {% site_name %} to create a PagerTree incident when + a check goes down, and resolve it when a check goes back up.

    + +

    Integration Settings

    + +
    + {% csrf_token %} +
    + +
    + + + {% if form.value.errors %} +
    + {{ form.value.errors|join:"" }} +
    + {% endif %} +
    +
    +
    +
    + +
    +
    +
    +
    +
    +{% endblock %} diff --git a/templates/integrations/pagertree_description.html b/templates/integrations/pagertree_description.html new file mode 100644 index 00000000..11718355 --- /dev/null +++ b/templates/integrations/pagertree_description.html @@ -0,0 +1,5 @@ +{% load humanize %} +{{ check.name_then_code }} is {{ check.status }}. +{% if check.status == "down" %} +Last ping was {{ check.last_ping|naturaltime }} +{% endif %} diff --git a/templates/integrations/pagertree_title.html b/templates/integrations/pagertree_title.html new file mode 100644 index 00000000..b537551e --- /dev/null +++ b/templates/integrations/pagertree_title.html @@ -0,0 +1 @@ +{{ check.name_then_code }} is {{ check.status }}