mirror of https://github.com/zulip/zulip.git
Add pingdom integration.
This commit is contained in:
parent
fe77559164
commit
44ed9da7f0
|
@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Added documentation on using Hubot to integrate with useful services
|
||||
not yet integrated with Zulip directly (e.g. Google Hangouts).
|
||||
- Added new management command to test sending email from Zulip.
|
||||
- Added Pingdom integration.
|
||||
- Refactored the Zulip puppet modules to be more modular.
|
||||
- Refactored the Tornado event system, fixing old memory leaks.
|
||||
- Implemented running queue processors multithreaded in development,
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
|
@ -164,6 +164,12 @@
|
|||
<span class="integration-label">Phabricator</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="integration-lozenge integration-pingdom">
|
||||
<a class="integration-link integration-pingdom" href="#pingdom">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/pingdom.png" alt="Pingdom logo" />
|
||||
<span class="integration-label">Pingdom</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="integration-lozenge integration-pivotal">
|
||||
<a class="integration-link integration-pivotal" href="#pivotal">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/pivotal.png" alt="Pivotal logo" />
|
||||
|
@ -1236,7 +1242,7 @@ key = NAGIOS_BOT_API_KEY
|
|||
<div id="phabricator" class="integration-instructions">
|
||||
|
||||
|
||||
<p>Zulip supports Phabricator integration and can notify you of the
|
||||
<p>Zulip supports integration with Phabricator and can notify you of the
|
||||
latest items in your Phabricator feed.</p>
|
||||
|
||||
<p>You can follow the instructions at
|
||||
|
@ -1248,11 +1254,41 @@ key = NAGIOS_BOT_API_KEY
|
|||
|
||||
</div>
|
||||
|
||||
<div id="pingdom" class="integration-instructions">
|
||||
|
||||
<p>Zulip supports integration with Pingdom and can notify you of
|
||||
uptime status changes from your Pingdom dashboard.</p>
|
||||
|
||||
<p>First, create the stream you'd like to use for Pingdom notifications,
|
||||
and subscribe all interested parties to this stream. We
|
||||
recommend the name <code>pingdom</code>.</p>
|
||||
|
||||
<p><code>{{ external_api_uri }}/v1/external/pingdom?api_key=abcdefgh&stream=pingdom</code></p>
|
||||
|
||||
<p>where <code>api_key</code> is the API key of your Zulip bot,
|
||||
and <code>stream</code> is the stream name you want the
|
||||
notifications sent to.</p>
|
||||
|
||||
<p>Next, under following url: </p>
|
||||
<p><code>https://my.pingdom.com/reports/integration/settings</code></p>
|
||||
<p>create your integration by clicking on <code>Add Integration</code> button and filling form as following:</p>
|
||||
<img class="screenshot" src="/static/images/integrations/pingdom/001.png" />
|
||||
|
||||
<p>Last, during creating or editing your check, scroll down to <code>Connect Integrations</code>
|
||||
section and ensure your integration is checked</p>
|
||||
|
||||
<p><b>Congratulations! You're done!</b><br /> Example Zulip notification
|
||||
looks like this:</p>
|
||||
|
||||
<img class="screenshot" src="/static/images/integrations/pingdom/002.png" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="pivotal" class="integration-instructions">
|
||||
|
||||
|
||||
<p>Zulip supports Pivotal Tracker integration and can notify you of changes
|
||||
<p>Zulip supports integration with Pivotal Tracker and can notify you of changes
|
||||
to the stories in your Pivotal Tracker project.</p>
|
||||
|
||||
<p>First, create the stream you'd like to use for Pivotal Tracker
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"check_id": 2048467,
|
||||
"check_name": "Test check",
|
||||
"check_type": "HTTP",
|
||||
"check_params": {
|
||||
"basic_auth": false,
|
||||
"encryption": false,
|
||||
"full_url": "http:\/\/someurl.com\/",
|
||||
"header": "User-Agent:Pingdom.com_bot_version_1.4_(http:\/\/www.pingdom.com\/)",
|
||||
"hostname": "someurl.com",
|
||||
"ipv6": false,
|
||||
"port": 80,
|
||||
"url": "\/"
|
||||
},
|
||||
"tags": [
|
||||
|
||||
],
|
||||
"previous_state": "UP",
|
||||
"current_state": "DOWN",
|
||||
"state_changed_timestamp": 1457939434,
|
||||
"state_changed_utc_time": "2016-03-14T07:10:34",
|
||||
"long_description": "Non-recoverable failure in name resolution",
|
||||
"description": "DNS error",
|
||||
"first_probe": {
|
||||
"ip": "85.17.156.99",
|
||||
"ipv6": "2001:1af8:4100:a09b::454",
|
||||
"location": "Amsterdam 5, Netherlands"
|
||||
},
|
||||
"second_probe": {
|
||||
"ip": "64.141.100.136",
|
||||
"ipv6": "",
|
||||
"location": "Calgary, Canada"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"check_id": 2051859,
|
||||
"check_name": "IMAP check",
|
||||
"check_type": "IMAP",
|
||||
"check_params": {
|
||||
"basic_auth": false,
|
||||
"encryption": true,
|
||||
"hostname": "imap.someurl.com",
|
||||
"ipv6": false,
|
||||
"port": 993
|
||||
},
|
||||
"tags": [],
|
||||
"previous_state": "DOWN",
|
||||
"current_state": "UP",
|
||||
"state_changed_timestamp": 1458070380,
|
||||
"state_changed_utc_time": "2016-03-15T19:33:00",
|
||||
"long_description": "OK",
|
||||
"description": "OK",
|
||||
"first_probe": {
|
||||
"ip": "69.64.56.47",
|
||||
"ipv6": "",
|
||||
"location": "St. Louis, MO"
|
||||
},
|
||||
"second_probe": {}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"check_id": 2051859,
|
||||
"check_name": "IMAP check",
|
||||
"check_type": "IMAP",
|
||||
"check_params": {
|
||||
"basic_auth": false,
|
||||
"encryption": true,
|
||||
"hostname": "imap.someurl.com",
|
||||
"ipv6": false,
|
||||
"port": 993
|
||||
},
|
||||
"tags": [],
|
||||
"previous_state": "UP",
|
||||
"current_state": "DOWN",
|
||||
"state_changed_timestamp": 1458069480,
|
||||
"state_changed_utc_time": "2016-03-15T19:18:00",
|
||||
"long_description": "Invalid hostname, address or socket",
|
||||
"description": "Unknown target",
|
||||
"first_probe": {
|
||||
"ip": "188.138.118.184",
|
||||
"ipv6": "",
|
||||
"location": "Strasbourg 2, France"
|
||||
},
|
||||
"second_probe": {
|
||||
"ip": "76.164.194.74",
|
||||
"ipv6": "2605:6f80:0:c::449",
|
||||
"location": "Las Vegas 2, NV"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"check_id": 2051844,
|
||||
"check_name": "SMTP check",
|
||||
"check_type": "SMTP",
|
||||
"check_params": {
|
||||
"basic_auth": false,
|
||||
"encryption": false,
|
||||
"hostname": "smtp.someurl.com",
|
||||
"ipv6": false,
|
||||
"port": 25
|
||||
},
|
||||
"tags": [],
|
||||
"previous_state": "UP",
|
||||
"current_state": "DOWN",
|
||||
"state_changed_timestamp": 1458068544,
|
||||
"state_changed_utc_time": "2016-03-15T19:02:24",
|
||||
"long_description": "Connection refused",
|
||||
"description": "Connection refused",
|
||||
"first_probe": {
|
||||
"ip": "174.34.162.242",
|
||||
"ipv6": "",
|
||||
"location": "Atlanta, GA"
|
||||
},
|
||||
"second_probe": {
|
||||
"ip": "64.141.100.136",
|
||||
"ipv6": "",
|
||||
"location": "Calgary, Canada"
|
||||
}
|
||||
}
|
|
@ -864,3 +864,71 @@ class TravisHookTests(AuthedTestCase):
|
|||
u"Details: [changes](https://github.com/hl7-fhir/fhir-sv"
|
||||
u"n/compare/6dccb98bcfd9...6c457d366a31), [build log](ht"
|
||||
u"tps://travis-ci.org/hl7-fhir/fhir-svn/builds/92495257)"))
|
||||
|
||||
|
||||
class PingdomHookTests(AuthedTestCase):
|
||||
STREAM_NAME = 'pingdom'
|
||||
TEST_USER_EMAIL = 'hamlet@zulip.com'
|
||||
URL_TEMPLATE = "/api/v1/external/pingdom?stream={stream}&api_key={api_key}"
|
||||
|
||||
def setUp(self):
|
||||
api_key = self.get_api_key(self.TEST_USER_EMAIL)
|
||||
self._url = self.URL_TEMPLATE.format(stream=self.STREAM_NAME, api_key=api_key)
|
||||
self.subscribe_to_stream(self.TEST_USER_EMAIL, self.STREAM_NAME)
|
||||
|
||||
def test_pingdom_from_up_to_down_http_check_message(self):
|
||||
"""
|
||||
Tests if pingdom http check from up to down is handled correctly
|
||||
"""
|
||||
body = self._get_fixture_data('http_up_to_down')
|
||||
self._send_post_request_with_params(body)
|
||||
|
||||
expected_message = u"Service someurl.com changed its HTTP status from UP to DOWN.\nDescription: Non-recoverable failure in name resolution."
|
||||
msg = self._get_recently_added_message()
|
||||
self.assertEqual(msg.subject, u"Test check status.")
|
||||
self.assertEqual(msg.content, expected_message)
|
||||
|
||||
def test_pingdom_from_up_to_down_smtp_check_message(self):
|
||||
"""
|
||||
Tests if pingdom smtp check from up to down is handled correctly
|
||||
"""
|
||||
body = self._get_fixture_data('smtp_up_to_down')
|
||||
self._send_post_request_with_params(body)
|
||||
|
||||
expected_message = u"Service smtp.someurl.com changed its SMTP status from UP to DOWN.\nDescription: Connection refused."
|
||||
msg = self._get_recently_added_message()
|
||||
self.assertEqual(msg.subject, u"SMTP check status.")
|
||||
self.assertEqual(msg.content, expected_message)
|
||||
|
||||
def test_pingdom_from_up_to_down_imap_check_message(self):
|
||||
"""
|
||||
Tests if pingdom imap check from up to down is handled correctly
|
||||
"""
|
||||
body = self._get_fixture_data('imap_up_to_down')
|
||||
self._send_post_request_with_params(body)
|
||||
|
||||
expected_message = u"Service imap.someurl.com changed its IMAP status from UP to DOWN.\nDescription: Invalid hostname, address or socket."
|
||||
msg = self._get_recently_added_message()
|
||||
self.assertEqual(msg.subject, u"IMAP check status.")
|
||||
self.assertEqual(msg.content, expected_message)
|
||||
|
||||
def test_pingdom_from_down_to_up_imap_check_message(self):
|
||||
"""
|
||||
Tests if pingdom imap check from down to up is handled correctly
|
||||
"""
|
||||
body = self._get_fixture_data('imap_down_to_up')
|
||||
self._send_post_request_with_params(body)
|
||||
|
||||
expected_message = u"Service imap.someurl.com changed its IMAP status from DOWN to UP."
|
||||
msg = self._get_recently_added_message()
|
||||
self.assertEqual(msg.subject, u"IMAP check status.")
|
||||
self.assertEqual(msg.content, expected_message)
|
||||
|
||||
def _get_recently_added_message(self):
|
||||
return Message.objects.filter().order_by('-id')[0]
|
||||
|
||||
def _get_fixture_data(self, name):
|
||||
return ujson.dumps(ujson.loads(self.fixture_data('pingdom', name)))
|
||||
|
||||
def _send_post_request_with_params(self, json):
|
||||
return self.client.post(self._url, json, stream_name=self.STREAM_NAME, content_type="application/json")
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
# Webhooks for external integrations.
|
||||
from __future__ import absolute_import
|
||||
from zerver.models import get_client
|
||||
from zerver.lib.actions import check_send_message
|
||||
from zerver.lib.response import json_success, json_error
|
||||
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view
|
||||
|
||||
import ujson
|
||||
|
||||
|
||||
PINGDOM_SUBJECT_TEMPLATE = '{name} status.'
|
||||
PINGDOM_MESSAGE_TEMPLATE = 'Service {service_url} changed its {type} status from {previous_state} to {current_state}.'
|
||||
PINGDOM_MESSAGE_DESCRIPTION_TEMPLATE = 'Description: {description}.'
|
||||
|
||||
|
||||
SUPPORTED_CHECK_TYPES = (
|
||||
'HTTP',
|
||||
'HTTP_CUSTOM'
|
||||
'HTTPS',
|
||||
'SMTP',
|
||||
'POP3',
|
||||
'IMAP',
|
||||
'PING',
|
||||
'DNS',
|
||||
'UDP',
|
||||
'PORT_TCP',
|
||||
)
|
||||
|
||||
|
||||
@api_key_only_webhook_view
|
||||
@has_request_variables
|
||||
def api_pingdom_webhook(request, user_profile, stream=REQ(default='pingdom')):
|
||||
payload = ujson.loads(request.body)
|
||||
check_type = get_check_type(payload)
|
||||
|
||||
if check_type in SUPPORTED_CHECK_TYPES:
|
||||
subject = get_subject_for_http_request(payload)
|
||||
body = get_body_for_http_request(payload)
|
||||
else:
|
||||
return json_error('Unsupported check_type: {check_type}'.format(check_type=check_type))
|
||||
|
||||
check_send_message(user_profile, get_client('ZulipPingdomWebhook'), 'stream', [stream], subject, body)
|
||||
return json_success()
|
||||
|
||||
|
||||
def get_subject_for_http_request(payload):
|
||||
return PINGDOM_SUBJECT_TEMPLATE.format(name=payload['check_name'])
|
||||
|
||||
|
||||
def get_body_for_http_request(payload):
|
||||
current_state = payload['current_state']
|
||||
previous_state = payload['previous_state']
|
||||
|
||||
data = {
|
||||
'service_url': payload['check_params']['hostname'],
|
||||
'previous_state': previous_state,
|
||||
'current_state': current_state,
|
||||
'type': get_check_type(payload)
|
||||
}
|
||||
body = PINGDOM_MESSAGE_TEMPLATE.format(**data)
|
||||
if current_state == 'DOWN' and previous_state == 'UP':
|
||||
description = PINGDOM_MESSAGE_DESCRIPTION_TEMPLATE.format(description=payload['long_description'])
|
||||
body += '\n{description}'.format(description=description)
|
||||
return body
|
||||
|
||||
|
||||
def get_check_type(payload):
|
||||
return payload['check_type']
|
|
@ -161,6 +161,7 @@ urlpatterns += patterns('zerver.views',
|
|||
url(r'^api/v1/external/zendesk$', 'webhooks.zendesk.api_zendesk_webhook'),
|
||||
url(r'^api/v1/external/pagerduty$', 'webhooks.pagerduty.api_pagerduty_webhook'),
|
||||
url(r'^api/v1/external/travis$', 'webhooks.travis.api_travis_webhook'),
|
||||
url(r'^api/v1/external/pingdom$', 'webhooks.pingdom.api_pingdom_webhook'),
|
||||
|
||||
url(r'^user_uploads/(?P<realm_id>(\d*|unk))/(?P<filename>.*)', 'get_uploaded_file'),
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue