Merge pull request #16404 from techhat/2014.7-pagerduty

Move PagerDuty to use native API instead of pygerduty
This commit is contained in:
Thomas S Hatch 2014-10-06 15:19:20 -06:00
commit 8556592959
2 changed files with 162 additions and 118 deletions

View File

@ -4,10 +4,9 @@ Module for Firing Events via PagerDuty
.. versionadded:: 2014.1.0 .. versionadded:: 2014.1.0
:depends: - pygerduty python module :configuration: This module can be used by specifying the name of a
:configuration: This module can be used by either passing a jid and password configuration profile in the minion config, minion pillar, or master
directly to send_message, or by specifying the name of a configuration config.
profile in the minion config, minion pillar, or master config.
For example: For example:
@ -18,40 +17,23 @@ Module for Firing Events via PagerDuty
pagerduty.subdomain: mysubdomain pagerduty.subdomain: mysubdomain
''' '''
HAS_LIBS = False # Import python libs
try: import yaml
import pygerduty import json
HAS_LIBS = True
except ImportError:
pass
__virtualname__ = 'pagerduty' # Import salt libs
import salt.utils.pagerduty
from salt._compat import string_types
def __virtual__(): def __virtual__():
''' '''
Only load this module if pygerduty is installed on this minion. No dependencies outside of what Salt itself requires
''' '''
if HAS_LIBS: return True
return __virtualname__
return False
def _get_pager(profile): def list_services(profile=None, api_key=None):
'''
Return the pagerduty connection
'''
creds = __salt__['config.option'](profile)
pager = pygerduty.PagerDuty(
creds.get('pagerduty.subdomain'),
creds.get('pagerduty.api_key'),
)
return pager
def list_services(profile):
''' '''
List services belonging to this account List services belonging to this account
@ -59,35 +41,12 @@ def list_services(profile):
pagerduty.list_services my-pagerduty-account pagerduty.list_services my-pagerduty-account
''' '''
pager = _get_pager(profile) return salt.utils.pagerduty.list_items(
ret = {} 'services', 'name', profile, api_key, opts=__opts__
for service in pager.services.list(): )
ret[service.name] = {
'acknowledgement_timeout': service.acknowledgement_timeout,
'auto_resolve_timeout': service.auto_resolve_timeout,
'created_at': service.created_at,
'deleted_at': service.deleted_at,
'description': service.description,
'email_filter_mode': service.email_filter_mode,
'email_incident_creation': service.email_incident_creation,
'id': service.id,
'incident_counts': {
'acknowledged': service.incident_counts.acknowledged,
'resolved': service.incident_counts.resolved,
'total': service.incident_counts.total,
'triggered': service.incident_counts.triggered,
},
'last_incident_timestamp': service.last_incident_timestamp,
'name': service.name,
'service_key': service.service_key,
'service_url': service.service_url,
'status': service.status,
'type': service.type,
}
return ret
def list_incidents(profile): def list_incidents(profile=None, api_key=None):
''' '''
List services belonging to this account List services belonging to this account
@ -95,59 +54,13 @@ def list_incidents(profile):
pagerduty.list_incidents my-pagerduty-account pagerduty.list_incidents my-pagerduty-account
''' '''
pager = _get_pager(profile) return salt.utils.pagerduty.list_items(
ret = {} 'incidents', 'id', profile, api_key, opts=__opts__
for incident in pager.incidents.list(): )
ret[incident.id] = {
'status': incident.status,
'service': {
'deleted_at': incident.service.deleted_at,
'id': incident.service.id,
'name': incident.service.name,
'html_url': incident.service.html_url,
},
'trigger_type': incident.trigger_type,
'escalation_policy': {
'id': incident.escalation_policy.id,
'name': incident.escalation_policy.name,
},
'assigned_to_user': incident.assigned_to_user,
'html_url': incident.html_url,
'last_status_change_on': incident.last_status_change_on,
'last_status_change_by': {},
'incident_key': incident.incident_key,
'created_on': incident.created_on,
'number_of_escalations': incident.number_of_escalations,
'incident_number': incident.incident_number,
'resolved_by_user': {},
'trigger_details_html_url': incident.trigger_details_html_url,
'id': incident.id,
'trigger_summary_data': {
'subject': None,
},
}
if hasattr(incident.trigger_summary_data, 'subject'):
ret[incident.id]['trigger_summary_data']['subject'] = \
incident.trigger_summary_data.subject
if hasattr(incident, 'resolved_by_user'):
ret[incident.id]['resolved_by_user'] = {
'id': incident.resolved_by_user.id,
'name': incident.resolved_by_user.name,
'html_url': incident.resolved_by_user.html_url,
'email': incident.resolved_by_user.email,
}
if hasattr(incident.last_status_change_by, 'id'):
ret[incident.id]['last_status_change_by'] = {
'id': incident.last_status_change_by.id,
'name': incident.last_status_change_by.name,
'html_url': incident.last_status_change_by.html_url,
'email': incident.last_status_change_by.email,
}
return ret
def create_event(service_key, description, details, incident_key=None, def create_event(service_key=None, description=None, details=None,
profile=None): incident_key=None, profile=None):
''' '''
Create an event in PagerDuty. Designed for use in states. Create an event in PagerDuty. Designed for use in states.
@ -155,7 +68,7 @@ def create_event(service_key, description, details, incident_key=None,
pagerduty.create_event <service_key> <description> <details> \ pagerduty.create_event <service_key> <description> <details> \
profile=my-pagerduty-account profile=my-pagerduty-account
:
The following parameters are required: The following parameters are required:
service_key service_key
@ -171,12 +84,25 @@ def create_event(service_key, description, details, incident_key=None,
This refers to the configuration profile to use to connect to the This refers to the configuration profile to use to connect to the
PagerDuty service. PagerDuty service.
''' '''
pager = _get_pager(profile) trigger_url = 'https://events.pagerduty.com/generic/2010-04-15/create_event.json'
event = pager.create_event(
service_key=service_key, if isinstance(details, string_types):
description=description, details = yaml.safe_load(details)
details=details, if isinstance(details, string_types):
event_type='trigger', details = {'details': details}
incident_key=incident_key,
) ret = json.loads(salt.utils.pagerduty.query(
return {'incident_key': str(event)} method='POST',
profile=profile,
api_key=service_key,
data={
'service_key': service_key,
'incident_key': incident_key,
'event_type': 'trigger',
'description': description,
'details': details,
},
url=trigger_url,
opts=__opts__
))
return ret

118
salt/utils/pagerduty.py Normal file
View File

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
'''
Library for interacting with PagerDuty API
.. versionadded:: 2014.7.0
:configuration: This module can be used by specifying the name of a
configuration profile in the minion config, minion pillar, or master
config.
For example:
.. code-block:: yaml
my-pagerduty-account:
pagerduty.subdomain: mysubdomain
pagerduty.api_key: F3Rbyjbve43rfFWf2214
'''
import json
import requests
import logging
from salt.version import __version__
log = logging.getLogger(__name__)
def query(method='GET', profile=None, url=None, path='api/v1',
action=None, api_key=None, service=None, params=None,
data=None, subdomain=None, client_url=None, description=None,
opts=None, verify_ssl=True):
'''
Query the PagerDuty API
'''
user_agent = 'SaltStack {0}'.format(__version__)
if opts is None:
opts = {}
if profile is not None:
creds = opts.get(profile)
else:
creds = {}
if api_key is not None:
creds['pagerduty.api_key'] = api_key
if service is not None:
creds['pagerduty.service'] = service
if subdomain is not None:
creds['pagerduty.subdomain'] = subdomain
if client_url is None:
client_url = 'https://{0}.pagerduty.com'.format(
creds['pagerduty.subdomain']
)
if url is None:
url = 'https://{0}.pagerduty.com/{1}/{2}'.format(
creds['pagerduty.subdomain'],
path,
action
)
if params is None:
params = {}
if data is None:
data = {}
data['client'] = user_agent
data['service_key'] = creds['pagerduty.service']
data['client_url'] = client_url
if 'event_type' not in data:
data['event_type'] = 'trigger'
if 'description' not in data:
if not description:
data['description'] = 'SaltStack Event Triggered'
else:
data['description'] = description
headers = {
'User-Agent': user_agent,
'Authorization': 'Token token={0}'.format(creds['pagerduty.api_key'])
}
if method == 'GET':
data = {}
else:
headers['Content-type'] = 'application/json'
result = requests.request(
method,
url,
headers=headers,
params=params,
data=json.dumps(data),
verify=verify_ssl
)
return result.text
def list_items(action, key, profile=None, api_key=None, opts=None):
'''
List items belonging to an API call. Used for list_services() and
list_incidents()
'''
items = json.loads(query(
profile=profile,
api_key=api_key,
action=action,
opts=opts
))
ret = {}
for item in items[action]:
ret[item[key]] = item
return ret