oncall-engine/engine/apps/alerts/utils.py
Michael Derynck 6b40f95033 World, meet OnCall!
Co-authored-by: Eve832 <eve.meelan@grafana.com>
    Co-authored-by: Francisco Montes de Oca <nevermind89x@gmail.com>
    Co-authored-by: Ildar Iskhakov <ildar.iskhakov@grafana.com>
    Co-authored-by: Innokentii Konstantinov <innokenty.konstantinov@grafana.com>
    Co-authored-by: Julia <ferril.darkdiver@gmail.com>
    Co-authored-by: maskin25 <kengurek@gmail.com>
    Co-authored-by: Matias Bordese <mbordese@gmail.com>
    Co-authored-by: Matvey Kukuy <motakuk@gmail.com>
    Co-authored-by: Michael Derynck <michael.derynck@grafana.com>
    Co-authored-by: Richard Hartmann <richih@richih.org>
    Co-authored-by: Robby Milo <robbymilo@fastmail.com>
    Co-authored-by: Timur Olzhabayev <timur.olzhabayev@grafana.com>
    Co-authored-by: Vadim Stepanov <vadimkerr@gmail.com>
    Co-authored-by: Yulia Shanyrova <yulia.shanyrova@grafana.com>
2022-06-03 08:09:47 -06:00

91 lines
3.7 KiB
Python

import ipaddress
import json
import socket
from typing import Tuple
from urllib.parse import urlparse
import requests
OUTGOING_WEBHOOK_TIMEOUT = 10
def render_relative_timeline(log_created_at, alert_group_started_at):
time_delta = log_created_at - alert_group_started_at
seconds = int(time_delta.total_seconds())
days, seconds = divmod(seconds, 86400)
hours, seconds = divmod(seconds, 3600)
minutes, seconds = divmod(seconds, 60)
if days > 0:
return "%dd%dh%dm%ds" % (days, hours, minutes, seconds)
elif hours > 0:
return "%dh%dm%ds" % (hours, minutes, seconds)
elif minutes > 0:
return "%dm%ds" % (minutes, seconds)
else:
return "%ds" % (seconds,)
def render_curl_command(webhook_url, http_request_type, post_kwargs):
if http_request_type == "POST":
curl_request = "curl -X POST"
if "auth" in post_kwargs:
curl_request += "\n-u ****"
if "headers" in post_kwargs:
curl_request += "\n-H ****"
if "json" in post_kwargs:
curl_request += "\n-d '{}'".format(json.dumps(post_kwargs["json"], indent=2, sort_keys=True))
curl_request += "\n{}".format(webhook_url)
elif http_request_type == "GET":
curl_request = f"curl -X GET {webhook_url}"
else:
raise Exception("Unsupported http method")
return curl_request
def request_outgoing_webhook(webhook_url, http_request_type, post_kwargs={}) -> Tuple[bool, str]:
if http_request_type not in ["POST", "GET"]:
raise Exception(f"Wrong http_method parameter: {http_request_type}")
parsed_url = urlparse(webhook_url)
# ensure the url looks like url
if parsed_url.scheme not in ["http", "https"]:
return False, "Malformed url"
if not parsed_url.netloc:
return False, "Malformed url"
# Get the ip address of the webhook url and check if it belongs to the private network
try:
webhook_url_ip_address = socket.gethostbyname(parsed_url.netloc)
except socket.gaierror:
return False, "Cannot resolve name in url"
if ipaddress.ip_address(socket.gethostbyname(webhook_url_ip_address)).is_private:
return False, "This url is not supported for outgoing webhooks"
try:
if http_request_type == "POST":
r = requests.post(webhook_url, timeout=OUTGOING_WEBHOOK_TIMEOUT, **post_kwargs)
elif http_request_type == "GET":
r = requests.get(webhook_url, timeout=OUTGOING_WEBHOOK_TIMEOUT)
else:
raise Exception()
r.raise_for_status()
return True, "OK 200"
except requests.exceptions.HTTPError:
return False, "HTTP error {}".format(r.status_code)
except requests.exceptions.SSLError:
return False, "ssl certificate error"
except requests.exceptions.ConnectionError:
return False, "Connection error happened. Probably that's because of network or proxy."
except requests.exceptions.MissingSchema:
return False, "Url {} is incorrect. http:// or https:// might be missing.".format(webhook_url)
except requests.exceptions.ChunkedEncodingError:
return False, "File content or headers might be wrong."
except requests.exceptions.InvalidURL:
return False, "Url {} is incorrect".format(webhook_url)
except requests.exceptions.TooManyRedirects:
return False, "Multiple redirects happened. That's suspicious!"
except requests.exceptions.Timeout:
return False, f"Request timeout {OUTGOING_WEBHOOK_TIMEOUT} secs exceeded."
except requests.exceptions.RequestException: # This is the correct syntax
return False, "Failed to call outgoing webhook"
except Exception:
return False, "Failed to call outgoing webhook"