Unverified Commit e1a0733e by Cory Lee Committed by GitHub

Coryleeio/pingdom alert creation script (#4480)

* Added pingdom check creation utility + README + examples.

* docs

* Add comment explaining why we update every check
parent f7e666ae
Pingdom check creation utility
************
To use:
.. code-block:: bash
$ virtualenv -p /usr/bin/python .Python
$ source .Python/bin/activate
$ pip install -r requirements.txt
# Put the export commands in your bashrc or something similar
$ export PINGDOM_EMAIL=MY_USERNAME
$ export PINGDOM_PASSWORD=MY_PASSWORD
$ export PINGDOM_API_KEY=MY_API_KEY
$ python create_pingdom_alerts.py --alert-config-file ~/my-config-file
There is an [example](example.yml) config file located in this directory.
import json
import click
import yaml
import requests
import json
class PingdomInvalidResponse(Exception):
pass
@click.command()
@click.option('--noop', is_flag=True, help="Don't apply changes to Pingdom.")
@click.option('--pingdom-email', required=True,
help='Email to use to speak with Pingdom.',
envvar='PINGDOM_EMAIL')
@click.option('--pingdom-password', required=True,
help='Password to use to speak with Pingdom.',
envvar='PINGDOM_PASSWORD')
@click.option('--pingdom-api-key', required=True,
help='API Key to use to speak with Pingdom.',
envvar='PINGDOM_API_KEY')
@click.option('--alert-config-file', required=True,
help="path to config file",
envvar='ALERT_CONFIG_FILE')
def main(noop, pingdom_email, pingdom_password,
pingdom_api_key,
alert_config_file):
with open(alert_config_file, 'r') as stream:
config_file_content = yaml.load(stream)
config_file_content = replace_user_names_with_userids(pingdom_email,
pingdom_password,
pingdom_api_key,
config_file_content)
config_file_content = integration_names_to_ids(config_file_content)
checks_by_hostname = build_checks_by_hostname(pingdom_email,
pingdom_password,
pingdom_api_key)
hostnames = checks_by_hostname.keys()
for alert_config in config_file_content['checks']:
if alert_config['host'] not in hostnames:
# Create new check
if noop:
print("Would CREATE: {0}, but you set the noop flag.".format(
alert_config))
else:
print("CREATE: {0}".format(alert_config))
create_check(pingdom_email, pingdom_password,
pingdom_api_key, alert_config)
else:
# Updating existing check
existing_check = checks_by_hostname[alert_config['host']]
if noop:
print("""
Has changes, would UPDATE: {0},
but you set the noop flag.
""".format(alert_config))
else:
print("Attempting UPDATE: {0}".format(alert_config))
# We always update because the parameters to POST check
# and the paramters returned by GET check differ.
# It would be difficult to figure out if changes
# have occured.
update_check(pingdom_email, pingdom_password,
pingdom_api_key, existing_check['id'],
alert_config)
def replace_user_names_with_userids(pingdom_email,
pingdom_password,
pingdom_api_key,
config_file_content):
user_ids_by_name = build_userid_by_name(
pingdom_email, pingdom_password, pingdom_api_key)
for alert in config_file_content['checks']:
user_ids = []
if 'users' in alert:
for user in alert['users']:
if 'userids' in alert:
user_ids.extend(
map(lambda x: x.strip(), alert['userids'].split(',')))
if user not in user_ids_by_name:
raise PingdomInvalidResponse(
'Pingdom has no user with the name {0}'.format(user))
user_id = user_ids_by_name[user]
user_ids.append(user_id)
del alert['users']
alert['userids'] = ','.join(map(str, user_ids))
return config_file_content
def integration_names_to_ids(config_file_content):
integration_ids_by_name = config_file_content['integration_name_to_id_map']
for alert in config_file_content['checks']:
integration_ids = []
if 'integrations' in alert:
for integration in alert['integrations']:
if('integrationids' in alert):
integration_ids.extend(
alert['integrationids'].split(','))
if integration not in integration_ids_by_name.keys():
print(
"""
You specified a integration
that does not exist in
our map.
""")
print(
"""
You may just need to add it to the
build_integrations_by_name method
pingdom does not have an API for this presently...
""")
exit(1)
integration_id = integration_ids_by_name[integration]
integration_ids.append(integration_id)
del alert['integrations']
alert['integrationids'] = ','.join(map(str, integration_ids))
return config_file_content
def create_check(pingdom_email, pingdom_password, pingdom_api_key, payload):
try:
response = requests.post("https://api.pingdom.com/api/2.1/checks",
headers={
'app-key': pingdom_api_key
},
auth=(pingdom_email, pingdom_password),
params=payload)
response.raise_for_status()
print("Create successful")
except requests.exceptions.HTTPError:
print_error_prefix()
print_request_and_response(response)
exit(1)
return json.loads(response.content)
def update_check(pingdom_email, pingdom_password,
pingdom_api_key, id, payload):
if('type' in payload):
del(payload['type'])
try:
url = "https://api.pingdom.com/api/2.1/checks/{0}".format(id)
response = requests.put(url,
headers={
'app-key': pingdom_api_key
},
auth=(pingdom_email, pingdom_password),
params=payload)
response.raise_for_status()
print("Update successful")
except requests.exceptions.HTTPError:
print_error_prefix()
print_request_and_response(response)
exit(1)
return json.loads(response.content)
def list_checks(pingdom_email, pingdom_password, pingdom_api_key):
try:
response = requests.get("https://api.pingdom.com/api/2.1/checks",
headers={
'app-key': pingdom_api_key
},
auth=(pingdom_email, pingdom_password))
response.raise_for_status()
except requests.exceptions.HTTPError:
print_error_prefix()
print_request_and_response(response)
exit(1)
return json.loads(response.content)['checks']
def list_users(pingdom_email, pingdom_password, pingdom_api_key):
try:
response = requests.get("https://api.pingdom.com/api/2.1/users",
headers={
'app-key': pingdom_api_key
},
auth=(pingdom_email, pingdom_password))
response.raise_for_status()
except requests.exceptions.HTTPError:
print_error_prefix()
print_request_and_response(response)
exit(1)
return json.loads(response.content)
def build_checks_by_hostname(pingdom_email, pingdom_password, pingdom_api_key):
checks = list_checks(pingdom_email, pingdom_password, pingdom_api_key)
checks_by_hostname = {}
for check in checks:
checks_by_hostname[str(check['hostname'])] = check
return checks_by_hostname
def build_userid_by_name(pingdom_email, pingdom_password, pingdom_api_key):
user_content = list_users(
pingdom_email, pingdom_password, pingdom_api_key)
users = user_content['users']
user_ids_by_name = {}
for user in users:
user_ids_by_name[user['name'].strip()] = user['id']
return user_ids_by_name
def print_request_and_response(response):
print("Request:")
for key in response.request.headers:
print("{0}: {1}".format(key, response.request.headers[key]))
print("")
print(response.request.body)
print("------------------")
print("Response:")
for key in response.headers:
print("{0}: {1}".format(key, response.headers[key]))
print("")
print(response.content)
print("------------------")
def print_error_prefix():
print("Got error from pingdom, dumping request/response:")
if __name__ == "__main__":
main()
checks:
- name: "Cory test alert"
host: "corylee.io"
type: "http"
encryption: false
users:
- "Pager"
- name: "google HTTPS"
host: "google.com"
type: "http"
encryption: true
# Translated to userids for the API call, looked up via the API
users:
- "Pager"
# Translated to integrationids for the API call, looked up from the integration_name_to_id_map
# because no API endpoint exists
integrations:
- "Opsgenie"
# Names to id map for integrations
integration_name_to_id_map:
Opsgenie: 1
Learner - OpsGenie: 2
api.opsgenie.com: 3
click==6.7
PyYAML==3.12
requests==2.18.4
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment