Skip to content

Instantly share code, notes, and snippets.

@mikey-
Last active April 15, 2020 17:29
Show Gist options
  • Save mikey-/64a9f265cb0d7154f69bad27f9ce9860 to your computer and use it in GitHub Desktop.
Save mikey-/64a9f265cb0d7154f69bad27f9ce9860 to your computer and use it in GitHub Desktop.
Junk Python to Manage Pingdom Uptime Check Contacts

Managing Pingdom Check Contact Info

Hello and good morning to you and your family!

I Made This A Long Time Ago

Anyway this an overview of some old code and some other comments about things of that nature. Throughout this document I refer to this section in apology for not having the better sense to write the code better in the first place.

Junk Becoming and Code Overview

The Python code here is about four years old and isn't what I would call "good", or "secure"; however, it is what I would call, "junk". Honestly, it's probably better for your health to avoid using the code, but I can't stop you... You're too powerful.

If it's junk, why keep it?

Well, yeah! Right?! you're totally right! I should just delete it!

Look, I get it, I'm sure this kind of junk seems verrrry static, in the sense that it may appear to be nothing more than inanimate, slivers of a past frame of mind, an incorrect one at that - so moved on from that it's rarely thought of, if not forgotten entirely; until it's unfortunate revival as a thing to be learned from. A fate of wasteful analysis and re-use, is all that can await this junk!!!

Junk Becoming

I'm sentimental lil' froggy, and I'm imaginative too! I love the idea that the things I hold onto are powerful fibers of embodiment past, current and future; slivers - cleaned and combed, becoming the yarn from which my congnition is weaved and my body sewed.

Okay, buddy...

Maybe it's cheezy2u but ^that's^ the truth!

Also, ummmmm I initially made this gist public and updated the README because I would repeatedly come across this code, as it was stored in a secret gist, named README.md. This was more than enough to entice me to open it, every. single. time. and either feel nostalgic about how much fun I had writing this small automation, or anxious at how many problems there were with it.

Eventually, I decided to update the gist so that I'll always know what it is, just by looking at the name.

Eventuallyier, I decided to update the gist so that this README appeared above the code and I figured while I'm at it, why not share a little about myself?

So what does the code does?

Well, this here code was built to automate the rotation of a Pingdom alert's contact. The code is a Python 2 script, which executes the following:

  1. Reads a configuration file for a list of Pingdom alert & contact information
  2. Retrieving the first contact in the list
  3. Updates the Pingdom alert with the retrieved contact information
  4. Moves the retrieved contact to the end of the list

Why does it do what it does?

The script was created to be run periodically, with the goal of implementing the concept of an on-call roster.

Alternatively, the script can be used in an ad-hoc fashion to simply replace a Pingdom alert's contact with another contact.

Configuration

This Script Modifies Your Configuration File

Whether you use a different configuration path or use the default location for your configuration file, this script will modify the file.

After the script updates the contact information for a Pingdom Check, it remove the contact from the sequence of mappings in the configuration file and re-add it to the end of the sequence.

I'm so sorry

Using your own config

You may pass in your own configuration file with the -c option but you don't need to, as by default, the script wil try to read ./config.yaml for it's configuraiton.

Configuration Attributes

This describes the configuration itself and what it represents for an example of the configuration, see config.yaml.

The script expects that it's configuration is specified in a Yaml file. The Yaml file must consist of the following top-level mappings:

  • auth: Represents the authentication information used by the script to connect to Pingdom.

    auth maps a set of three mappings, which are:

    • account-email: Your Pingdom account's email address
    • app-key: One of your Pingdom account's app-keys
    • credentials: The secret key to the app-key you used in auth.app-key
  • check_id: Represents which represents the ID of the Pingdom Check you want to manage the contact information of.

  • contacts: Represents the contact information to be used, by the script, to modify the contact information of the Pingdom Check specified by check_id.

    contacts maps to a sequence of mappings, each mapping in the sequence maps to:

    • id: A string which represents a contact's ID.
    • name: A string which represents the name of a contact. The contact who's name is specified should have an ID which matches the ID which is specified in the same mapping as the contact's name. Confusing, I'm sorry :)

Usage

If you want to use the script, here's how to do it and what to expect...

Put The Top Down 4 Some Ventilation

  1. Touchscreen Navigate to config.py and download that config!

  2. Touchscreen Navigate to update_pingdom_contact.py and download that script!

Do it now!

Chuck In Your Own Config Values

Please, if any part of you still loves me, do as I say...

  1. Open your new config.py file in your least fav editor

  2. Overwrite the values for each of the three mappings in the auth mapping

  3. Overwrite the value of the check_id mapping

  4. Overwrite the values for each of the two mappings within each of the three sequence elements in the contacts mapping

Okay, one last favour :0 please save your work ;) Thank me later (;

But Don't Use Python 3

This script probably won't work with Python 3 (please believe and understand, I Made This A Long Time Ago)

Executing The Script

Simply run python update_contact_in_pingdom_check.py in your terminal. If you're passing in a config file, simply run python update_contact_in_pingdom_check.py -c /path/to/config.yaml in your terminal.

When The Script Fails

If the update fails, in any way, it will not rotate any contacts it hasn't already rotated. How confusing and annoying!

Output

While you'll probably observe some differences, like:

  • Contact IDs
  • Contact Names
  • Check ID

You should see something like following text in the output of the Python script

Automating the rotation of a contacts for pingdom alerts
Getting config from config.yaml
Attempting to open config.yaml for reading
Done.

Getting next contact...
Done. Next contact is Mike Mudstone , id: 420666

Getting check id...
Done. Updating check: 6966669

Making request to modify contact in check: 6966669
Success: {'body': '{"message":"Modification of check was successful!"}',
'code': 200}

Rotating contacts...
Attempting to open config.yaml for writing
Done. Next contact will be Steven Robinson ASE, editor of First Contact; not to be confused with this script, which is merely the editor of the first contact... of your config.yaml :0
Oh yeah, id: 123457

Please Like and Subscribe

Thank you for your time and the grace of your loving energy

A Word From My Sponsors

May your neighbours respect you,
Trouble neglect you,
Angels protect you,
And heaven accept you.

- Drake

GoodBye

Love From Mikey B

auth:
account-email: ’someone@email.com'
app-key: ‘1234567890'
credentials: '01234567890123456789012345678901234567890123456789012345'
check_id: '1234567'
contacts:
- id: '123456'
name: 'Ikey Battistonm'
- id: '123457'
name: 'Mikey Battiston'
- id: '123458'
name: 'Bikey Mattiston'
__author__ = 'Mikey'
__version__ = '0.0.1'
__purpose__ = 'Automating the rotation of a contacts for pingdom alerts'
print (__purpose__)
import json
import yaml
import urllib
import urllib2
import argparse
parser = argparse.ArgumentParser(description='')
parser.add_argument('-o', '--config_file', nargs='?', const='config.yaml', default='config.yaml', required=False)
args = parser.parse_args()
config_file = args.config_file
def get_config():
print "Attempting to open %s for reading" % config_file
with open("%s" % (config_file), 'r') as config_file_stream:
config = yaml.load(config_file_stream)
return config
def modify_contact_in_pingdom_check(options):
url = options['url']
app_key = options['app-key']
check_id = options['check_id']
contact_id = options['contact_id']
credentials = options['credentials']
account_email = options['account-email']
try:
print "Making request to modify contact in check: %s" % options['check_id']
opener = urllib2.build_opener(urllib2.HTTPSHandler)
data = {
'contactids' : "%s" % contact_id
}
data = urllib.urlencode(data)
headers = {
'App-Key' : app_key,
'Account-Email' : account_email,
'Authorization' : 'Basic %s' % credentials
}
request = urllib2.Request(url, data=data, headers=headers)
request.get_method = lambda: 'PUT'
response = opener.open(request)
return {
"body" : response.read(),
"code" : response.getcode()
}
except urllib2.HTTPError, e:
return {
"body" : e.read(),
"code" : e.getcode()
}
def cycle_contacts():
print "Attempting to open %s for writing" % config_file
with open("%s" % (config_file), 'r') as config_file_stream:
config = yaml.load(config_file_stream)
contact_to_rotate = config['contacts'].pop(0)
config['contacts'].append(contact_to_rotate)
with open("%s" % (config_file), 'w') as config_file_stream:
yaml.dump(config, config_file_stream, default_flow_style=False)
contact = config['contacts'][0]
return contact
if __name__ == "__main__":
print "Getting config from %s" % config_file
try:
config = get_config()
print "Done."
print ""
except Exception as e:
print "Error: Unable to retrieve config from %s" % config_file
print e.message, e.args
exit(1)
print "Getting next contact..."
try:
contact = config['contacts'][0]
print "Done. Next contact is %s, id: %s" % (contact['name'],contact['id'])
print ""
except Exception as e:
print "Error: Unable to retrieve contact"
print e.message, e.args
exit(1)
print "Getting check id..."
try:
check_id = config['check_id']
print "Done. Updating check: %s" % check_id
print ""
except Exception as e:
print "Error: Unable to retrieve check_id"
print e.message, e.args
exit(1)
options = {
'url' : "https://api.pingdom.com/api/2.0/checks/%s" % check_id,
'check_id' : check_id,
'contact_id' : contact['id'],
'credentials' : config['auth']['credentials'],
'app-key' : config['auth']['app-key'],
'account-email' : config['auth']['account-email']
}
response = modify_contact_in_pingdom_check(options)
if response['code'] is not 200:
print "Error: %s" % response;
exit(1)
else:
print "Success: %s" % response;
print ""
print "Rotating contacts..."
try:
next_contact = cycle_contacts()
print "Done. Next contact will be %s, id: %s" % (next_contact['name'],next_contact['id'])
except Exception as e:
print "Error: Unable to rotate contacts in %s" % config_file
print e.message, e.args
exit(1)
exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment