forked from GithubBackups/healthchecks
Remove legacy webhook formats (newline-separated fields and the post_data key) from the Channel model
This commit is contained in:
parent
6ebae33579
commit
84a4de32cc
@ -460,29 +460,7 @@ class Channel(models.Model):
|
|||||||
def webhook_spec(self, status):
|
def webhook_spec(self, status):
|
||||||
assert self.kind == "webhook"
|
assert self.kind == "webhook"
|
||||||
|
|
||||||
if not self.value.startswith("{"):
|
|
||||||
parts = self.value.split("\n")
|
|
||||||
url_down = parts[0]
|
|
||||||
url_up = parts[1] if len(parts) > 1 else ""
|
|
||||||
post_data = parts[2] if len(parts) > 2 else ""
|
|
||||||
|
|
||||||
return {
|
|
||||||
"method": "POST" if post_data else "GET",
|
|
||||||
"url": url_down if status == "down" else url_up,
|
|
||||||
"body": post_data,
|
|
||||||
"headers": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
doc = json.loads(self.value)
|
doc = json.loads(self.value)
|
||||||
if "post_data" in doc:
|
|
||||||
# Legacy "post_data" in doc -- use the legacy fields
|
|
||||||
return {
|
|
||||||
"method": "POST" if doc["post_data"] else "GET",
|
|
||||||
"url": doc["url_down"] if status == "down" else doc["url_up"],
|
|
||||||
"body": doc["post_data"],
|
|
||||||
"headers": doc["headers"],
|
|
||||||
}
|
|
||||||
|
|
||||||
if status == "down" and "method_down" in doc:
|
if status == "down" and "method_down" in doc:
|
||||||
return {
|
return {
|
||||||
"method": doc["method_down"],
|
"method": doc["method_down"],
|
||||||
|
@ -5,116 +5,6 @@ from hc.test import BaseTestCase
|
|||||||
|
|
||||||
|
|
||||||
class ChannelModelTestCase(BaseTestCase):
|
class ChannelModelTestCase(BaseTestCase):
|
||||||
def test_webhook_spec_handles_plain_single_address(self):
|
|
||||||
c = Channel(kind="webhook")
|
|
||||||
c.value = "http://example.org"
|
|
||||||
self.assertEqual(
|
|
||||||
c.down_webhook_spec,
|
|
||||||
{"method": "GET", "url": "http://example.org", "body": "", "headers": {}},
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
c.up_webhook_spec, {"method": "GET", "url": "", "body": "", "headers": {}}
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_webhook_spec_handles_plain_pair(self):
|
|
||||||
c = Channel(kind="webhook")
|
|
||||||
c.value = "http://example.org\nhttp://example.com/up/"
|
|
||||||
self.assertEqual(
|
|
||||||
c.down_webhook_spec,
|
|
||||||
{"method": "GET", "url": "http://example.org", "body": "", "headers": {}},
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
c.up_webhook_spec,
|
|
||||||
{
|
|
||||||
"method": "GET",
|
|
||||||
"url": "http://example.com/up/",
|
|
||||||
"body": "",
|
|
||||||
"headers": {},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_webhook_spec_handles_plain_post(self):
|
|
||||||
c = Channel(kind="webhook")
|
|
||||||
c.value = "http://example.org\n\nhello world"
|
|
||||||
self.assertEqual(
|
|
||||||
c.down_webhook_spec,
|
|
||||||
{
|
|
||||||
"method": "POST",
|
|
||||||
"url": "http://example.org",
|
|
||||||
"body": "hello world",
|
|
||||||
"headers": {},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
c.up_webhook_spec,
|
|
||||||
{"method": "POST", "url": "", "body": "hello world", "headers": {}},
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_webhook_spec_handles_legacy_get(self):
|
|
||||||
c = Channel(kind="webhook")
|
|
||||||
c.value = json.dumps(
|
|
||||||
{
|
|
||||||
"url_down": "http://example.org",
|
|
||||||
"url_up": "http://example.org/up/",
|
|
||||||
"headers": {"X-Name": "value"},
|
|
||||||
"post_data": "",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
c.down_webhook_spec,
|
|
||||||
{
|
|
||||||
"method": "GET",
|
|
||||||
"url": "http://example.org",
|
|
||||||
"body": "",
|
|
||||||
"headers": {"X-Name": "value"},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
c.up_webhook_spec,
|
|
||||||
{
|
|
||||||
"method": "GET",
|
|
||||||
"url": "http://example.org/up/",
|
|
||||||
"body": "",
|
|
||||||
"headers": {"X-Name": "value"},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_webhook_spec_handles_legacy_post(self):
|
|
||||||
c = Channel(kind="webhook")
|
|
||||||
c.value = json.dumps(
|
|
||||||
{
|
|
||||||
"url_down": "http://example.org",
|
|
||||||
"url_up": "http://example.org/up/",
|
|
||||||
"headers": {"X-Name": "value"},
|
|
||||||
"post_data": "hello world",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
c.down_webhook_spec,
|
|
||||||
{
|
|
||||||
"method": "POST",
|
|
||||||
"url": "http://example.org",
|
|
||||||
"body": "hello world",
|
|
||||||
"headers": {"X-Name": "value"},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
c.up_webhook_spec,
|
|
||||||
{
|
|
||||||
"method": "POST",
|
|
||||||
"url": "http://example.org/up/",
|
|
||||||
"body": "hello world",
|
|
||||||
"headers": {"X-Name": "value"},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_webhook_spec_handles_mixed(self):
|
def test_webhook_spec_handles_mixed(self):
|
||||||
c = Channel(kind="webhook")
|
c = Channel(kind="webhook")
|
||||||
c.value = json.dumps(
|
c.value = json.dumps(
|
||||||
|
@ -28,7 +28,14 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
def test_webhook(self, mock_get):
|
def test_webhook(self, mock_get):
|
||||||
self._setup_data("webhook", "http://example")
|
definition = {
|
||||||
|
"method_down": "GET",
|
||||||
|
"url_down": "http://example",
|
||||||
|
"body_down": "",
|
||||||
|
"headers_down": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
self._setup_data("webhook", json.dumps(definition))
|
||||||
mock_get.return_value.status_code = 200
|
mock_get.return_value.status_code = 200
|
||||||
|
|
||||||
self.channel.notify(self.check)
|
self.channel.notify(self.check)
|
||||||
@ -41,7 +48,14 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
|
|
||||||
@patch("hc.api.transports.requests.request", side_effect=Timeout)
|
@patch("hc.api.transports.requests.request", side_effect=Timeout)
|
||||||
def test_webhooks_handle_timeouts(self, mock_get):
|
def test_webhooks_handle_timeouts(self, mock_get):
|
||||||
self._setup_data("webhook", "http://example")
|
definition = {
|
||||||
|
"method_down": "GET",
|
||||||
|
"url_down": "http://example",
|
||||||
|
"body_down": "",
|
||||||
|
"headers_down": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
self._setup_data("webhook", json.dumps(definition))
|
||||||
self.channel.notify(self.check)
|
self.channel.notify(self.check)
|
||||||
|
|
||||||
n = Notification.objects.get()
|
n = Notification.objects.get()
|
||||||
@ -49,23 +63,28 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
|
|
||||||
@patch("hc.api.transports.requests.request", side_effect=ConnectionError)
|
@patch("hc.api.transports.requests.request", side_effect=ConnectionError)
|
||||||
def test_webhooks_handle_connection_errors(self, mock_get):
|
def test_webhooks_handle_connection_errors(self, mock_get):
|
||||||
self._setup_data("webhook", "http://example")
|
definition = {
|
||||||
|
"method_down": "GET",
|
||||||
|
"url_down": "http://example",
|
||||||
|
"body_down": "",
|
||||||
|
"headers_down": {},
|
||||||
|
}
|
||||||
|
self._setup_data("webhook", json.dumps(definition))
|
||||||
self.channel.notify(self.check)
|
self.channel.notify(self.check)
|
||||||
|
|
||||||
n = Notification.objects.get()
|
n = Notification.objects.get()
|
||||||
self.assertEqual(n.error, "Connection failed")
|
self.assertEqual(n.error, "Connection failed")
|
||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
|
||||||
def test_webhooks_ignore_up_events(self, mock_get):
|
|
||||||
self._setup_data("webhook", "http://example", status="up")
|
|
||||||
self.channel.notify(self.check)
|
|
||||||
|
|
||||||
self.assertFalse(mock_get.called)
|
|
||||||
self.assertEqual(Notification.objects.count(), 0)
|
|
||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
def test_webhooks_handle_500(self, mock_get):
|
def test_webhooks_handle_500(self, mock_get):
|
||||||
self._setup_data("webhook", "http://example")
|
definition = {
|
||||||
|
"method_down": "GET",
|
||||||
|
"url_down": "http://example",
|
||||||
|
"body_down": "",
|
||||||
|
"headers_down": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
self._setup_data("webhook", json.dumps(definition))
|
||||||
mock_get.return_value.status_code = 500
|
mock_get.return_value.status_code = 500
|
||||||
|
|
||||||
self.channel.notify(self.check)
|
self.channel.notify(self.check)
|
||||||
@ -75,8 +94,14 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
def test_webhooks_support_variables(self, mock_get):
|
def test_webhooks_support_variables(self, mock_get):
|
||||||
template = "http://host/$CODE/$STATUS/$TAG1/$TAG2/?name=$NAME"
|
definition = {
|
||||||
self._setup_data("webhook", template)
|
"method_down": "GET",
|
||||||
|
"url_down": "http://host/$CODE/$STATUS/$TAG1/$TAG2/?name=$NAME",
|
||||||
|
"body_down": "",
|
||||||
|
"headers_down": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
self._setup_data("webhook", json.dumps(definition))
|
||||||
self.check.name = "Hello World"
|
self.check.name = "Hello World"
|
||||||
self.check.tags = "foo bar"
|
self.check.tags = "foo bar"
|
||||||
self.check.save()
|
self.check.save()
|
||||||
@ -93,7 +118,14 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
def test_webhooks_handle_variable_variables(self, mock_get):
|
def test_webhooks_handle_variable_variables(self, mock_get):
|
||||||
self._setup_data("webhook", "http://host/$$NAMETAG1")
|
definition = {
|
||||||
|
"method_down": "GET",
|
||||||
|
"url_down": "http://host/$$NAMETAG1",
|
||||||
|
"body_down": "",
|
||||||
|
"headers_down": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
self._setup_data("webhook", json.dumps(definition))
|
||||||
self.check.tags = "foo bar"
|
self.check.tags = "foo bar"
|
||||||
self.check.save()
|
self.check.save()
|
||||||
|
|
||||||
@ -105,8 +137,14 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
def test_webhooks_support_post(self, mock_request):
|
def test_webhooks_support_post(self, mock_request):
|
||||||
template = "http://example.com\n\nThe Time Is $NOW"
|
definition = {
|
||||||
self._setup_data("webhook", template)
|
"method_down": "POST",
|
||||||
|
"url_down": "http://example.com",
|
||||||
|
"body_down": "The Time Is $NOW",
|
||||||
|
"headers_down": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
self._setup_data("webhook", json.dumps(definition))
|
||||||
self.check.save()
|
self.check.save()
|
||||||
|
|
||||||
self.channel.notify(self.check)
|
self.channel.notify(self.check)
|
||||||
@ -122,9 +160,14 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
def test_webhooks_dollarsign_escaping(self, mock_get):
|
def test_webhooks_dollarsign_escaping(self, mock_get):
|
||||||
# If name or tag contains what looks like a variable reference,
|
# If name or tag contains what looks like a variable reference,
|
||||||
# that should be left alone:
|
# that should be left alone:
|
||||||
|
definition = {
|
||||||
|
"method_down": "GET",
|
||||||
|
"url_down": "http://host/$NAME",
|
||||||
|
"body_down": "",
|
||||||
|
"headers_down": {},
|
||||||
|
}
|
||||||
|
|
||||||
template = "http://host/$NAME"
|
self._setup_data("webhook", json.dumps(definition))
|
||||||
self._setup_data("webhook", template)
|
|
||||||
self.check.name = "$TAG1"
|
self.check.name = "$TAG1"
|
||||||
self.check.tags = "foo"
|
self.check.tags = "foo"
|
||||||
self.check.save()
|
self.check.save()
|
||||||
@ -137,8 +180,14 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
def test_webhook_fires_on_up_event(self, mock_get):
|
def test_webhooks_handle_up_events(self, mock_get):
|
||||||
self._setup_data("webhook", "http://foo\nhttp://bar", status="up")
|
definition = {
|
||||||
|
"method_up": "GET",
|
||||||
|
"url_up": "http://bar",
|
||||||
|
"body_up": "",
|
||||||
|
"headers_up": {},
|
||||||
|
}
|
||||||
|
self._setup_data("webhook", json.dumps(definition), status="up")
|
||||||
|
|
||||||
self.channel.notify(self.check)
|
self.channel.notify(self.check)
|
||||||
|
|
||||||
@ -147,38 +196,10 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
def test_webhooks_handle_unicode_post_body(self, mock_request):
|
def test_webhooks_handle_noop_up_events(self, mock_get):
|
||||||
template = "http://example.com\n\n(╯°□°)╯︵ ┻━┻"
|
|
||||||
self._setup_data("webhook", template)
|
|
||||||
self.check.save()
|
|
||||||
|
|
||||||
self.channel.notify(self.check)
|
|
||||||
args, kwargs = mock_request.call_args
|
|
||||||
|
|
||||||
# unicode should be encoded into utf-8
|
|
||||||
self.assertIsInstance(kwargs["data"], bytes)
|
|
||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
|
||||||
def test_webhooks_handle_json_value(self, mock_request):
|
|
||||||
definition = {
|
|
||||||
"method_down": "GET",
|
|
||||||
"url_down": "http://foo.com",
|
|
||||||
"body_down": "",
|
|
||||||
"headers_down": {},
|
|
||||||
}
|
|
||||||
self._setup_data("webhook", json.dumps(definition))
|
|
||||||
self.channel.notify(self.check)
|
|
||||||
|
|
||||||
headers = {"User-Agent": "healthchecks.io"}
|
|
||||||
mock_request.assert_called_with(
|
|
||||||
"get", "http://foo.com", headers=headers, timeout=5
|
|
||||||
)
|
|
||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
|
||||||
def test_webhooks_handle_json_up_event(self, mock_request):
|
|
||||||
definition = {
|
definition = {
|
||||||
"method_up": "GET",
|
"method_up": "GET",
|
||||||
"url_up": "http://bar",
|
"url_up": "",
|
||||||
"body_up": "",
|
"body_up": "",
|
||||||
"headers_up": {},
|
"headers_up": {},
|
||||||
}
|
}
|
||||||
@ -186,8 +207,26 @@ class NotifyTestCase(BaseTestCase):
|
|||||||
self._setup_data("webhook", json.dumps(definition), status="up")
|
self._setup_data("webhook", json.dumps(definition), status="up")
|
||||||
self.channel.notify(self.check)
|
self.channel.notify(self.check)
|
||||||
|
|
||||||
headers = {"User-Agent": "healthchecks.io"}
|
self.assertFalse(mock_get.called)
|
||||||
mock_request.assert_called_with("get", "http://bar", headers=headers, timeout=5)
|
self.assertEqual(Notification.objects.count(), 0)
|
||||||
|
|
||||||
|
@patch("hc.api.transports.requests.request")
|
||||||
|
def test_webhooks_handle_unicode_post_body(self, mock_request):
|
||||||
|
definition = {
|
||||||
|
"method_down": "POST",
|
||||||
|
"url_down": "http://foo.com",
|
||||||
|
"body_down": "(╯°□°)╯︵ ┻━┻",
|
||||||
|
"headers_down": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
self._setup_data("webhook", json.dumps(definition))
|
||||||
|
self.check.save()
|
||||||
|
|
||||||
|
self.channel.notify(self.check)
|
||||||
|
args, kwargs = mock_request.call_args
|
||||||
|
|
||||||
|
# unicode should be encoded into utf-8
|
||||||
|
self.assertIsInstance(kwargs["data"], bytes)
|
||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
def test_webhooks_handle_post_headers(self, mock_request):
|
def test_webhooks_handle_post_headers(self, mock_request):
|
||||||
|
@ -23,7 +23,18 @@ class ChannelsTestCase(BaseTestCase):
|
|||||||
|
|
||||||
def test_it_shows_webhook_post_data(self):
|
def test_it_shows_webhook_post_data(self):
|
||||||
ch = Channel(kind="webhook", project=self.project)
|
ch = Channel(kind="webhook", project=self.project)
|
||||||
ch.value = "http://down.example.com\nhttp://up.example.com\nfoobar"
|
ch.value = json.dumps(
|
||||||
|
{
|
||||||
|
"method_down": "POST",
|
||||||
|
"url_down": "http://down.example.com",
|
||||||
|
"body_down": "foobar",
|
||||||
|
"headers_down": {},
|
||||||
|
"method_up": "GET",
|
||||||
|
"url_up": "http://up.example.com",
|
||||||
|
"body_up": "",
|
||||||
|
"headers_up": {},
|
||||||
|
}
|
||||||
|
)
|
||||||
ch.save()
|
ch.save()
|
||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
|
@ -74,7 +74,14 @@ class LogTestCase(BaseTestCase):
|
|||||||
|
|
||||||
def test_it_shows_webhook_notification(self):
|
def test_it_shows_webhook_notification(self):
|
||||||
ch = Channel(kind="webhook", project=self.project)
|
ch = Channel(kind="webhook", project=self.project)
|
||||||
ch.value = "foo/$NAME"
|
ch.value = json.dumps(
|
||||||
|
{
|
||||||
|
"method_down": "GET",
|
||||||
|
"url_down": "foo/$NAME",
|
||||||
|
"body_down": "",
|
||||||
|
"headers_down": {},
|
||||||
|
}
|
||||||
|
)
|
||||||
ch.save()
|
ch.save()
|
||||||
|
|
||||||
Notification(owner=self.check, channel=ch, check_status="down").save()
|
Notification(owner=self.check, channel=ch, check_status="down").save()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user