Browse Source

Test LineNotify integration with healthcheck

pull/415/head
carson.wang 4 years ago
committed by Pēteris Caune
parent
commit
65b65188d1
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
15 changed files with 200 additions and 0 deletions
  1. +11
    -0
      hc/api/models.py
  2. +14
    -0
      hc/api/transports.py
  3. +2
    -0
      hc/front/forms.py
  4. +16
    -0
      hc/front/tests/test_add_linenotify.py
  5. +1
    -0
      hc/front/urls.py
  6. +22
    -0
      hc/front/views.py
  7. +3
    -0
      hc/settings.py
  8. BIN
      static/img/integrations/linenotify.png
  9. BIN
      static/img/integrations/setup_linenotify_1.png
  10. BIN
      static/img/integrations/setup_linenotify_2.png
  11. BIN
      static/img/integrations/setup_linenotify_3.png
  12. +11
    -0
      templates/front/channels.html
  13. +9
    -0
      templates/front/welcome.html
  14. +105
    -0
      templates/integrations/add_linenotify.html
  15. +6
    -0
      templates/integrations/linenotify_message.html

+ 11
- 0
hc/api/models.py View File

@ -51,6 +51,7 @@ CHANNEL_KINDS = (
("zulip", "Zulip"), ("zulip", "Zulip"),
("spike", "Spike"), ("spike", "Spike"),
("call", "Phone Call"), ("call", "Phone Call"),
("linenotify", "LineNotify"),
) )
PO_PRIORITIES = {-2: "lowest", -1: "low", 0: "normal", 1: "high", 2: "emergency"} PO_PRIORITIES = {-2: "lowest", -1: "low", 0: "normal", 1: "high", 2: "emergency"}
@ -463,6 +464,8 @@ class Channel(models.Model):
return transports.Spike(self) return transports.Spike(self)
elif self.kind == "call": elif self.kind == "call":
return transports.Call(self) return transports.Call(self)
elif self.kind == "linenotify":
return transports.LineNotify(self)
else: else:
raise NotImplementedError("Unknown channel kind: %s" % self.kind) raise NotImplementedError("Unknown channel kind: %s" % self.kind)
@ -747,6 +750,14 @@ class Channel(models.Model):
doc = json.loads(self.value) doc = json.loads(self.value)
return doc["to"] return doc["to"]
@property
def linenotify_token(self):
assert self.kind == "linenotify"
if not self.value.startswith("{"):
return self.value
doc = json.loads(self.value)
return doc["token"]
class Notification(models.Model): class Notification(models.Model):
class Meta: class Meta:


+ 14
- 0
hc/api/transports.py View File

@ -619,3 +619,17 @@ class Spike(HttpTransport):
} }
return self.post(url, json=payload, headers=headers) return self.post(url, json=payload, headers=headers)
class LineNotify(HttpTransport):
URL = "https://notify-api.line.me/api/notify"
def notify(self, check):
headers = {
"Content-Type": "multipart/form-data",
"Authorization": "Bearer %s" % settings.LINE_NOTIFY_ACCESS_TOKEN,
}
payload = {
"message": tmpl("linenotify_message.html", check=check)
}
return self.post(URL, headers=headers, params=payload)

+ 2
- 0
hc/front/forms.py View File

@ -104,6 +104,8 @@ class AddOpsGenieForm(forms.Form):
region = forms.ChoiceField(initial="us", choices=(("us", "US"), ("eu", "EU"))) region = forms.ChoiceField(initial="us", choices=(("us", "US"), ("eu", "EU")))
key = forms.CharField(max_length=40) key = forms.CharField(max_length=40)
class AddLineNotifyForm(forms.Form):
token = forms.CharField(max_length=40)
PRIO_CHOICES = [ PRIO_CHOICES = [
("-2", "Lowest Priority"), ("-2", "Lowest Priority"),


+ 16
- 0
hc/front/tests/test_add_linenotify.py View File

@ -0,0 +1,16 @@
from django.test.utils import override_settings
from hc.api.models import Channel
from hc.test import BaseTestCase
@override_settings(LINE_NOTIFY_ACCESS_TOKEN="foo")
class AddLineNotifyTestCase(BaseTestCase):
url = "/integrations/add_linenotify/"
def setUp(self):
super(AddLineNotifyTestCase, self).setUp()
self.url = "/projects/%s/add_linenotify/" % self.project.code
def test_instructions_work(self):
self.client.login(username="[email protected]", password="password")
r = self.client.get(self.url)
self.assertContains(r, "LineNotify")

+ 1
- 0
hc/front/urls.py View File

@ -79,6 +79,7 @@ project_urls = [
path("add_whatsapp/", views.add_whatsapp, name="hc-add-whatsapp"), path("add_whatsapp/", views.add_whatsapp, name="hc-add-whatsapp"),
path("add_zulip/", views.add_zulip, name="hc-add-zulip"), path("add_zulip/", views.add_zulip, name="hc-add-zulip"),
path("add_spike/", views.add_spike, name="hc-add-spike"), path("add_spike/", views.add_spike, name="hc-add-spike"),
path("add_linenotify/", views.add_linenotify, name="hc-add-linenotify"),
path("badges/", views.badges, name="hc-badges"), path("badges/", views.badges, name="hc-badges"),
path("checks/", views.my_checks, name="hc-checks"), path("checks/", views.my_checks, name="hc-checks"),
path("checks/add/", views.add_check, name="hc-add-check"), path("checks/add/", views.add_check, name="hc-add-check"),


+ 22
- 0
hc/front/views.py View File

@ -273,6 +273,7 @@ def index(request):
"enable_telegram": settings.TELEGRAM_TOKEN is not None, "enable_telegram": settings.TELEGRAM_TOKEN is not None,
"enable_trello": settings.TRELLO_APP_KEY is not None, "enable_trello": settings.TRELLO_APP_KEY is not None,
"enable_whatsapp": settings.TWILIO_USE_WHATSAPP, "enable_whatsapp": settings.TWILIO_USE_WHATSAPP,
"enable_linenotify": settings.LINE_NOTIFY_ACCESS_TOKEN is not None,
"registration_open": settings.REGISTRATION_OPEN, "registration_open": settings.REGISTRATION_OPEN,
} }
@ -711,6 +712,7 @@ def channels(request, code):
"enable_telegram": settings.TELEGRAM_TOKEN is not None, "enable_telegram": settings.TELEGRAM_TOKEN is not None,
"enable_trello": settings.TRELLO_APP_KEY is not None, "enable_trello": settings.TRELLO_APP_KEY is not None,
"enable_whatsapp": settings.TWILIO_USE_WHATSAPP, "enable_whatsapp": settings.TWILIO_USE_WHATSAPP,
"enable_linenotify": settings.LINE_NOTIFY_ACCESS_TOKEN is not None,
"use_payments": settings.USE_PAYMENTS, "use_payments": settings.USE_PAYMENTS,
} }
@ -1381,6 +1383,26 @@ def add_opsgenie(request, code):
ctx = {"page": "channels", "project": project, "form": form} ctx = {"page": "channels", "project": project, "form": form}
return render(request, "integrations/add_opsgenie.html", ctx) return render(request, "integrations/add_opsgenie.html", ctx)
# @require_setting("LINE_NOTIFY_ACCESS_TOKEN")
@login_required
def add_linenotify(request, code):
project = _get_project_for_user(request, code)
if request.method == "POST":
form = forms.AddLineNotifyForm(request.POST)
if form.is_valid():
channel = Channel(project=project, kind="linenotify")
channel.value = form.cleaned_data["value"]
channel.save()
channel.assign_all_checks()
return redirect("hc-p-channels", project.code)
else:
form = forms.AddLineNotifyForm()
ctx = {"page": "channels", "project": project, "form": form}
return render(request, "integrations/add_linenotify.html", ctx)
@login_required @login_required
def add_victorops(request, code): def add_victorops(request, code):


+ 3
- 0
hc/settings.py View File

@ -208,6 +208,9 @@ PD_VENDOR_KEY = os.getenv("PD_VENDOR_KEY")
# Trello # Trello
TRELLO_APP_KEY = os.getenv("TRELLO_APP_KEY") TRELLO_APP_KEY = os.getenv("TRELLO_APP_KEY")
# Line notify integration
LINE_NOTIFY_ACCESS_TOKEN = os.getenv("LINE_NOTIFY_ACCESS_TOKEN")
# Matrix # Matrix
MATRIX_HOMESERVER = os.getenv("MATRIX_HOMESERVER") MATRIX_HOMESERVER = os.getenv("MATRIX_HOMESERVER")
MATRIX_USER_ID = os.getenv("MATRIX_USER_ID") MATRIX_USER_ID = os.getenv("MATRIX_USER_ID")


BIN
static/img/integrations/linenotify.png View File

Before After
Width: 512  |  Height: 512  |  Size: 18 KiB

BIN
static/img/integrations/setup_linenotify_1.png View File

Before After
Width: 2030  |  Height: 1626  |  Size: 253 KiB

BIN
static/img/integrations/setup_linenotify_2.png View File

Before After
Width: 996  |  Height: 1472  |  Size: 121 KiB

BIN
static/img/integrations/setup_linenotify_3.png View File

Before After
Width: 1034  |  Height: 906  |  Size: 79 KiB

+ 11
- 0
templates/front/channels.html View File

@ -412,6 +412,17 @@
<a href="{% url 'hc-add-zulip' project.code %}" class="btn btn-primary">Add Integration</a> <a href="{% url 'hc-add-zulip' project.code %}" class="btn btn-primary">Add Integration</a>
</li> </li>
{% comment %} {% if enable_linenotify %} {% endcomment %}
<li>
<img src="{% static 'img/integrations/linenotify.png' %}"
class="icon" alt="LineNotify icon" />
<h2>LineNotify</h2>
<p>Get a LineNotify message when a check goes up or down.</p>
<a href="{% url 'hc-add-linenotify' project.code %}" class="btn btn-primary">Add Integration</a>
</li>
{% comment %} {% endif %} {% endcomment %}
<li class="link-to-github"> <li class="link-to-github">
<img src="{% static 'img/integrations/missing.png' %}" <img src="{% static 'img/integrations/missing.png' %}"
class="icon" alt="Suggest New Integration" /> class="icon" alt="Suggest New Integration" />


+ 9
- 0
templates/front/welcome.html View File

@ -642,6 +642,15 @@
</h3> </h3>
</div> </div>
</div> </div>
{% comment %} {% if enable_linenotify %} {% endcomment %}
<div class="col-lg-2 col-md-3 col-sm-4 col-xs-6">
<div class="integration">
<img src="{% static 'img/integrations/linenotify.png' %}" class="icon" alt="" />
<h3>LineNotify<br><small>Chat</small></h3>
</div>
</div>
{% comment %} {% endif %} {% endcomment %}
</div> </div>
<div class="row tour-section"> <div class="row tour-section">


+ 105
- 0
templates/integrations/add_linenotify.html View File

@ -0,0 +1,105 @@
{% extends "base.html" %}
{% load humanize static hc_extras %}
{% block title %}LineNotify Integration for {% site_name %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-12">
<h1>LineNotify</h1>
<p><a href="https://notify-bot.line.me/en/">LineNotify</a>
allows you to send web notifications directly to your LINE chats.
If you use or plan on using LineNotify,
you can set up {% site_name %} to post status updates directly to an appropriate LineNotify channel.
Here are a few steps that can integrate it with your {% site_name %} account.</p>
<h2>Setup Guide</h2>
<div class="row ai-step">
<div class="col-sm-6">
<span class="step-no"></span>
<p>
Log into your Line account,
go to <strong>My Pages</strong> in the upper right corner.
In the <strong>My Pages</strong>, scroll to the bottom of the page,
and click on <strong>Generate token</strong> button.
</p>
</div>
<div class="col-sm-6">
<div class="marker-wrap">
<span style="left: 77%; top: 14%;" class="marker"></span>
<img
class="ai-guide-screenshot"
alt="Screenshot"
src="{% static 'img/integrations/setup_linenotify_1.png' %}" />
</div>
</div>
</div>
<div class="row ai-step">
<div class="col-sm-6">
<span class="step-no"></span>
<p>
It will pop up the <strong>Generate token</strong> Form.
Fill out the details, and click the button.
</p>
</div>
<div class="col-sm-6">
<img
class="ai-guide-screenshot"
alt="Screenshot"
src="{% static 'img/integrations/setup_linenotify_2.png' %}">
</div>
</div>
<div class="row ai-step">
<div class="col-sm-6">
<span class="step-no"></span>
<p>
Copy the displayed <strong>Token</strong> and paste it
in the form below.
Save the integration, and it's done!
</p>
</div>
<div class="col-sm-6">
<img
class="ai-guide-screenshot"
alt="Screenshot"
src="{% static 'img/integrations/setup_linenotify_3.png' %}">
</div>
</div>
<h2>Integration Settings</h2>
<form method="post" class="form-horizontal">
{% csrf_token %}
<div class="form-group {{ form.value.css_classes }}">
<label for="api-token" class="col-sm-2 control-label">API Token</label>
<div class="col-sm-10">
<input
id="api-token"
type="text"
class="form-control"
name="token"
placeholder=""
value="{{ form.token.value|default:"" }}">
{% if form.token.errors %}
<div class="help-block">
{{ form.token.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 %}

+ 6
- 0
templates/integrations/linenotify_message.html View File

@ -0,0 +1,6 @@
{% load humanize %}
{% if check.status == "down" %}
The check "{{ check.name_then_code }}" is <b>DOWN</b>. Last ping was {{ check.last_ping|naturaltime }}.
{% else %}
The check "{{ check.name_then_code }}" is now <b>UP</b>.
{% endif %}

Loading…
Cancel
Save