Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
integration: Add statuspage.io webhook integration.
- Loading branch information
1 parent
c98d355
commit 8844cfb
Showing
12 changed files
with
325 additions
and
0 deletions.
There are no files selected for viewing
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
Get Zulip notifications for your Statuspage.io subscriptions! | ||
|
||
{!create-stream.md!} | ||
|
||
{!create-bot-construct-url.md!} | ||
|
||
What company needs to do: | ||
Go to the **subscribers settings** in **notifications** tab and enable notifications delivery through **WEBHOOK**. | ||
|
||
![](/static/images/integrations/statuspage/001.png) | ||
|
||
In order to subscribe to a company's Statuspage.io notifications: | ||
|
||
1. Go to the company's Statuspage.io site (for instance, `example.statuspage.io`). | ||
2. Click on **SUBSCRIBE TO UPDATES** | ||
3. Enter the webhook URL constructed above in the **Target Webhook** field. | ||
4. Click on **SUBSCRIBE TO NOTIFICATIONS**. | ||
|
||
![](/static/images/integrations/statuspage/002.png) | ||
|
||
{!congrats.md!} | ||
|
||
![](/static/images/integrations/statuspage/003.png) |
32 changes: 32 additions & 0 deletions
32
zerver/webhooks/statuspage/fixtures/component_status_update.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"meta": { | ||
"unsubscribe": "http://mycompany24.statuspage.io/?unsubscribe=zjcdb6727vmj", | ||
"documentation": "http://doers.statuspage.io/customer-notifications/webhooks/", | ||
"generated_at": "2017-12-26T07:59:09.498Z" | ||
}, | ||
"page": { | ||
"id": "jb7j80lkgqvb", | ||
"status_indicator": "maintenance", | ||
"status_description": "Service Under Maintenance" | ||
}, | ||
"component": { | ||
"status": "under_maintenance", | ||
"name": "Database component", | ||
"created_at": "2017-12-26T07:57:28.743Z", | ||
"updated_at": "2017-12-26T07:59:09.371Z", | ||
"position": 3, | ||
"description": null, | ||
"showcase": true, | ||
"id": "sqm6pl84wzjc", | ||
"page_id": "jb7j80lkgqvb", | ||
"group_id": null | ||
}, | ||
"component_update": { | ||
"old_status": "operational", | ||
"new_status": "under_maintenance", | ||
"created_at": "2017-12-26T07:59:09.379Z", | ||
"component_type": "Component", | ||
"id": "nd963wv4j30b", | ||
"component_id": "sqm6pl84wzjc" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
{ | ||
"meta": { | ||
"unsubscribe": "http://mycompany24.statuspage.io/?unsubscribe=zjcdb6727vmj", | ||
"documentation": "http://doers.statuspage.io/customer-notifications/webhooks/", | ||
"generated_at": "2017-12-26T07:32:00.770Z" | ||
}, | ||
"page": { | ||
"id": "jb7j80lkgqvb", | ||
"status_indicator": "none", | ||
"status_description": "All Systems Operational" | ||
}, | ||
"incident": { | ||
"name": "Database query delays", | ||
"status": "identified", | ||
"created_at": "2017-12-26T07:32:00.507Z", | ||
"updated_at": "2017-12-26T07:32:00.603Z", | ||
"monitoring_at": null, | ||
"resolved_at": null, | ||
"impact": "none", | ||
"shortlink": "http://stspg.io/646947c1e", | ||
"postmortem_ignored": false, | ||
"postmortem_body": null, | ||
"postmortem_body_last_updated_at": null, | ||
"postmortem_published_at": null, | ||
"postmortem_notified_subscribers": false, | ||
"postmortem_notified_twitter": false, | ||
"backfilled": false, | ||
"scheduled_for": null, | ||
"scheduled_until": null, | ||
"scheduled_remind_prior": false, | ||
"scheduled_reminded_at": null, | ||
"impact_override": null, | ||
"scheduled_auto_in_progress": false, | ||
"scheduled_auto_completed": false, | ||
"id": "z3lct0r596n4", | ||
"page_id": "jb7j80lkgqvb", | ||
"incident_updates": [ | ||
{ | ||
"status": "identified", | ||
"body": "We just encountered that database queries are timing out resulting in inconvenience to our end users...we'll do quick fix latest by tommorow !!!", | ||
"created_at": "2017-12-26T07:32:00.548Z", | ||
"wants_twitter_update": false, | ||
"twitter_updated_at": null, | ||
"updated_at": "2017-12-26T07:32:00.548Z", | ||
"display_at": "2017-12-26T07:32:00.548Z", | ||
"affected_components": [ | ||
{ | ||
"code": "zvdm6f7gf76j", | ||
"name": "Management Portal (example)", | ||
"old_status": "operational", | ||
"new_status": "operational" | ||
} | ||
], | ||
"custom_tweet": null, | ||
"deliver_notifications": true, | ||
"id": "qm8bgczn0p2n", | ||
"incident_id": "z3lct0r596n4" | ||
} | ||
], | ||
"components": [ | ||
{ | ||
"status": "operational", | ||
"name": "Management Portal (example)", | ||
"created_at": "2017-12-25T18:44:27.901Z", | ||
"updated_at": "2017-12-25T18:44:27.901Z", | ||
"position": 2, | ||
"description": null, | ||
"showcase": true, | ||
"id": "zvdm6f7gf76j", | ||
"page_id": "jb7j80lkgqvb", | ||
"group_id": null | ||
} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
{ | ||
"meta": { | ||
"unsubscribe": "http://mycompany24.statuspage.io/?unsubscribe=zjcdb6727vmj", | ||
"documentation": "http://doers.statuspage.io/customer-notifications/webhooks/", | ||
"generated_at": "2017-12-26T07:37:21.000Z" | ||
}, | ||
"page": { | ||
"id": "jb7j80lkgqvb", | ||
"status_indicator": "none", | ||
"status_description": "All Systems Operational" | ||
}, | ||
"incident": { | ||
"name": "Database query delays", | ||
"status": "resolved", | ||
"created_at": "2017-12-26T07:32:00.507Z", | ||
"updated_at": "2017-12-26T07:37:20.837Z", | ||
"monitoring_at": null, | ||
"resolved_at": "2017-12-26T07:37:20.785Z", | ||
"impact": "none", | ||
"shortlink": "http://stspg.io/646947c1e", | ||
"postmortem_ignored": false, | ||
"postmortem_body": null, | ||
"postmortem_body_last_updated_at": null, | ||
"postmortem_published_at": null, | ||
"postmortem_notified_subscribers": false, | ||
"postmortem_notified_twitter": false, | ||
"backfilled": false, | ||
"scheduled_for": null, | ||
"scheduled_until": null, | ||
"scheduled_remind_prior": false, | ||
"scheduled_reminded_at": null, | ||
"impact_override": null, | ||
"scheduled_auto_in_progress": false, | ||
"scheduled_auto_completed": false, | ||
"id": "z3lct0r596n4", | ||
"page_id": "jb7j80lkgqvb", | ||
"incident_updates": [ | ||
{ | ||
"status": "resolved", | ||
"body": "The database issue is resolved.", | ||
"created_at": "2017-12-26T07:37:20.785Z", | ||
"wants_twitter_update": false, | ||
"twitter_updated_at": null, | ||
"updated_at": "2017-12-26T07:37:20.785Z", | ||
"display_at": "2017-12-26T07:37:20.785Z", | ||
"affected_components": [ | ||
{ | ||
"code": "zvdm6f7gf76j", | ||
"name": "Management Portal (example)", | ||
"old_status": "operational", | ||
"new_status": "operational" | ||
} | ||
], | ||
"custom_tweet": null, | ||
"deliver_notifications": true, | ||
"id": "cdwfdrjlp53y", | ||
"incident_id": "z3lct0r596n4" | ||
}, | ||
{ | ||
"status": "identified", | ||
"body": "We just encountered that database queries are timing out resulting in inconvenience to our end users...we'll do quick fix latest by tommorow !!!", | ||
"created_at": "2017-12-26T07:32:00.548Z", | ||
"wants_twitter_update": false, | ||
"twitter_updated_at": null, | ||
"updated_at": "2017-12-26T07:32:00.548Z", | ||
"display_at": "2017-12-26T07:32:00.548Z", | ||
"affected_components": [ | ||
{ | ||
"code": "zvdm6f7gf76j", | ||
"name": "Management Portal (example)", | ||
"old_status": "operational", | ||
"new_status": "operational" | ||
} | ||
], | ||
"custom_tweet": null, | ||
"deliver_notifications": true, | ||
"id": "qm8bgczn0p2n", | ||
"incident_id": "z3lct0r596n4" | ||
} | ||
], | ||
"components": [ | ||
{ | ||
"status": "operational", | ||
"name": "Management Portal (example)", | ||
"created_at": "2017-12-25T18:44:27.901Z", | ||
"updated_at": "2017-12-25T18:44:27.901Z", | ||
"position": 2, | ||
"description": null, | ||
"showcase": true, | ||
"id": "zvdm6f7gf76j", | ||
"page_id": "jb7j80lkgqvb", | ||
"group_id": null | ||
} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# -*- coding: utf-8 -*- | ||
from typing import Text | ||
from zerver.lib.test_classes import WebhookTestCase | ||
|
||
class StatuspageHookTests(WebhookTestCase): | ||
STREAM_NAME = 'statuspage-test' | ||
URL_TEMPLATE = u"/api/v1/external/statuspage?api_key={api_key}" | ||
|
||
def test_statuspage_incident(self) -> None: | ||
expected_subject = u"Database query delays: All Systems Operational" | ||
expected_message = u"**Database query delays** \n * State: **identified** \n \ | ||
* Description: We just encountered that database queries are timing out resulting in inconvenience \ | ||
to our end users...we'll do quick fix latest by tommorow !!!" | ||
self.send_and_test_stream_message('incident_created', | ||
expected_subject, | ||
expected_message, | ||
content_type="application/x-www-form-urlencoded") | ||
|
||
def test_statuspage_incident_update(self) -> None: | ||
expected_subject = u"Database query delays: All Systems Operational" | ||
expected_message = u"**Database query delays** \n * State: **resolved** \n \ | ||
* Description: The database issue is resolved." | ||
self.send_and_test_stream_message('incident_update', | ||
expected_subject, | ||
expected_message, | ||
content_type="application/x-www-form-urlencoded") | ||
|
||
def test_statuspage_component(self) -> None: | ||
expected_subject = u"Database component: Service Under Maintenance" | ||
expected_message = u"**Database component** has changed status \ | ||
from **operational** to **under_maintenance**" | ||
self.send_and_test_stream_message('component_status_update', | ||
expected_subject, | ||
expected_message, | ||
content_type="application/x-www-form-urlencoded") | ||
|
||
def get_body(self, fixture_name: Text) -> Text: | ||
return self.fixture_data("statuspage", fixture_name, file_type="json") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Webhooks for external integrations. | ||
from django.utils.translation import ugettext as _ | ||
from zerver.lib.actions import check_send_stream_message | ||
from zerver.lib.response import json_success | ||
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view | ||
from zerver.models import get_client, UserProfile | ||
from django.http import HttpRequest, HttpResponse | ||
from typing import Dict, Any, Text | ||
|
||
INCIDENT_TEMPLATE = u'**{name}** \n * State: **{state}** \n * Description: {content}' | ||
COMPONENT_TEMPLATE = u'**{name}** has changed status from **{old_status}** to **{new_status}**' | ||
TOPIC_TEMPLATE = u'{name}: {description}' | ||
|
||
def get_incident_events_body(payload: Dict[Text, Any]) -> Text: | ||
return INCIDENT_TEMPLATE.format( | ||
name = payload["incident"]["name"], | ||
state = payload["incident"]["status"], | ||
content = payload["incident"]["incident_updates"][0]["body"], | ||
) | ||
|
||
def get_components_update_body(payload: Dict[Text, Any]) -> Text: | ||
return COMPONENT_TEMPLATE.format( | ||
name = payload["component"]["name"], | ||
old_status = payload["component_update"]["old_status"], | ||
new_status = payload["component_update"]["new_status"], | ||
) | ||
|
||
def get_incident_topic(payload: Dict[Text, Any]) -> Text: | ||
return TOPIC_TEMPLATE.format( | ||
name = payload["incident"]["name"], | ||
description = payload["page"]["status_description"], | ||
) | ||
|
||
def get_component_topic(payload: Dict[Text, Any]) -> Text: | ||
return TOPIC_TEMPLATE.format( | ||
name = payload["component"]["name"], | ||
description = payload["page"]["status_description"], | ||
) | ||
|
||
@api_key_only_webhook_view('Statuspage') | ||
@has_request_variables | ||
def api_statuspage_webhook(request: HttpRequest, user_profile: UserProfile, | ||
payload: Dict[str, Any]=REQ(argument_type='body'), | ||
stream: str=REQ(default='statuspage-test')) -> HttpResponse: | ||
|
||
status = payload["page"]["status_indicator"] | ||
|
||
if status == "none": | ||
topic = get_incident_topic(payload) | ||
body = get_incident_events_body(payload) | ||
else: | ||
topic = get_component_topic(payload) | ||
body = get_components_update_body(payload) | ||
|
||
check_send_stream_message(user_profile, | ||
request.client, | ||
stream, | ||
topic, | ||
body) | ||
return json_success() |