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
:depends: - pygerduty python module
:configuration: This module can be used by either passing a jid and password
directly to send_message, or by specifying the name of a configuration
profile in the minion config, minion pillar, or master config.
: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:
@ -18,40 +17,23 @@ Module for Firing Events via PagerDuty
pagerduty.subdomain: mysubdomain
'''
HAS_LIBS = False
try:
import pygerduty
HAS_LIBS = True
except ImportError:
pass
# Import python libs
import yaml
import json
__virtualname__ = 'pagerduty'
# Import salt libs
import salt.utils.pagerduty
from salt._compat import string_types
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 __virtualname__
return False
return True
def _get_pager(profile):
'''
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):
def list_services(profile=None, api_key=None):
'''
List services belonging to this account
@ -59,35 +41,12 @@ def list_services(profile):
pagerduty.list_services my-pagerduty-account
'''
pager = _get_pager(profile)
ret = {}
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
return salt.utils.pagerduty.list_items(
'services', 'name', profile, api_key, opts=__opts__
)
def list_incidents(profile):
def list_incidents(profile=None, api_key=None):
'''
List services belonging to this account
@ -95,59 +54,13 @@ def list_incidents(profile):
pagerduty.list_incidents my-pagerduty-account
'''
pager = _get_pager(profile)
ret = {}
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
return salt.utils.pagerduty.list_items(
'incidents', 'id', profile, api_key, opts=__opts__
)
def create_event(service_key, description, details, incident_key=None,
profile=None):
def create_event(service_key=None, description=None, details=None,
incident_key=None, profile=None):
'''
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> \
profile=my-pagerduty-account
:
The following parameters are required:
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
PagerDuty service.
'''
pager = _get_pager(profile)
event = pager.create_event(
service_key=service_key,
description=description,
details=details,
event_type='trigger',
incident_key=incident_key,
)
return {'incident_key': str(event)}
trigger_url = 'https://events.pagerduty.com/generic/2010-04-15/create_event.json'
if isinstance(details, string_types):
details = yaml.safe_load(details)
if isinstance(details, string_types):
details = {'details': details}
ret = json.loads(salt.utils.pagerduty.query(
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