Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 27 additions & 11 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Pygerduty
=========

Python Library for PagerDuty's REST API and Events API. This library was originally written to support v1 and
is currently being updated to be compatible with v2 of the API. See "Migrating from v1 to v2" for more details.
is currently being updated to be compatible with v2 of the API. See "Migrating REST API from v1 to v2" for more details.

This library is currently evolving and backwards compatibility cannot always be guaranteed at this time.

Expand Down Expand Up @@ -42,35 +42,51 @@ see all available endpoints.
Top level resources will be accessible via the PagerDuty object and nested
resources available on containers returned from their parent resource.

For documentation on the Events API v2, please refer to the `Events API v2
Documentation <https://v2.developer.pagerduty.com/docs/events-api-v2/>`_ to
see all requirements. Additionally refer to the `Common Events Format (PD-CEF)
Documentation <https://support.pagerduty.com/docs/pd-cef>`_ to understand
the new fields, both optional and required.

Migrating from v1 to v2
=======================
Migrating REST API from v1 to v2
================================

In order to allow for a smooth transition between versions 1 and 2 of the library,
version 1 library remains in the file called `__init__.py` inside of the pygerduty directory.
In order to allow for a smooth transition between versions 1 and 2 of the Pygerduty library,
version 1 library remains in the file called ``__init__.py`` inside of the pygerduty directory.
Also in that directory you will see four other files:

- `v2.py` — This file contains all updated logic compatible with v2 of the API.
- `events.py` — PygerDuty also provides an Events API which is separate from the REST API that has had the recent update. Since the logic is mostly disjoint, we have created a new module for logic related to the Events API.
- `common.py` — This file contains all common functions used by both `v2.py` and `events.py`.
- `version.py` — Contains version info.
- ``v2.py`` — This file contains all updated logic compatible with v2 of the API.
- ``events.py`` — PygerDuty also provides an Events API which is separate from the REST API that has had the recent update. Since the logic is mostly disjoint, we have created a new module for logic related to the Events API.
- ``common.py`` — This file contains all common functions used by both `v2.py` and `events.py`.
- ``version.py`` — Contains version info.

See the examples below to see how this affects how you will instantiate a client in v2.


Migrating Events API from v1 to v2
==================================

In order to allow for a smooth transition between versions 1 and 2 of the Events API,
the version 1 class remains in the file called ``events.py`` inside of the pygerduty directory.
Also in that directory you will see a new file:

- ``events_v2.py`` — This file contains all updated logic compatible with the Events API v2.

Although the library still only contains one `Events` class, and that class still provides ``trigger_incident``, ``acknowledge_incident``, and ``resolve_incident`` methods, the fields required by PagerDuty have changed. Please take a moment to reference their `Events API v2 Documentation <https://v2.developer.pagerduty.com/docs/events-api-v2/>`_ and their explanation of their new `Common Events Format (PD-CEF) Documentation <https://support.pagerduty.com/docs/pd-cef>`_

Examples
========

Instantiating a client:

Version 1:
REST API Version 1:

::

import pygerduty
pager = pygerduty.PagerDuty("foobar", "SOMEAPIKEY123456")

Version 2:
REST API Version 2:

::

Expand Down
94 changes: 94 additions & 0 deletions pygerduty/events_v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# These methods are compatible with Pagerduty Events API v2
# - https://v2.developer.pagerduty.com/docs/events-api-v2
# - https://support.pagerduty.com/docs/pd-cef

from six.moves import urllib
from .exceptions import Error, IntegrationAPIError, BadRequest, NotFound
from .common import (
_json_dumper,
Requester,
)


INTEGRATION_API_URL = "https://events.pagerduty.com/v2/enqueue"


class Events(object):
def __init__(self, routing_key, requester=None):
self.routing_key = routing_key
self.headers = {
"Content-type": "application/json",
"Accept": "application/vnd.pagerduty+json;version=2",
"X-Routing-Key": self.routing_key
}
if requester is None:
self.requester = Requester()
else:
self.requester = requester

def enqueue(self, **kwargs):
# Required (according to documentation) PD-CEF fields
data = {"event_action": kwargs['event_action']}

# Determine if a 'payload' is required
payload_required = False
for key in ['payload', 'summary', 'source', 'severity',
'component', 'group', 'class', 'custom_details',
'timestamp']:
if key in kwargs:
payload_required = True

# Build optional payload from kwargs
if payload_required:
data['payload'] = kwargs.get('payload', {})

# Required payload fields
for key in ['summary', 'source', 'severity']:
if key in kwargs:
data['payload'][key] = kwargs[key]
elif key not in data['payload']:
raise KeyError(key)

# Optional payload fields
for key in ['component', 'group', 'class',
'custom_details', 'timestamp']:
if key in kwargs:
data['payload'][key] = kwargs[key]

# Optional event fields
for key in ['dedup_key', 'routing_key', 'images', 'links']:
if key in kwargs:
data[key] = kwargs[key]

request = urllib.request.Request(INTEGRATION_API_URL,
data=_json_dumper(data).encode('utf-8'),
headers=self.headers)
response = self.requester.execute_request(request)

if not response.get("status", "failure") == "success":
raise IntegrationAPIError(response["message"], kwargs['event_action'])
return response["dedup_key"]

def resolve_incident(self, **kwargs):
""" Causes the referenced incident to enter resolved state.
Send a resolve event when the problem that caused the initial
trigger has been fixed.
"""
kwargs['event_action'] = 'resolve'
return self.enqueue(**kwargs)

def acknowledge_incident(self, **kwargs):
""" Causes the referenced incident to enter the acknowledged state.
Send an acknowledge event when someone is presently working on the
incident.
"""
kwargs['event_action'] = 'acknowledge'
return self.enqueue(**kwargs)

def trigger_incident(self, **kwargs):
""" Report a new or ongoing problem. When PagerDuty receives a trigger,
it will either open a new incident, or add a new log entry to an
existing incident.
"""
kwargs['event_action'] = 'trigger'
return self.enqueue(**kwargs)
22 changes: 22 additions & 0 deletions tests/events_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
import json
import textwrap
import pygerduty.events
import pygerduty.events_v2

from pygerduty.events import INTEGRATION_API_URL
from pygerduty.events_v2 import INTEGRATION_API_URL as INTEGRATION_API_URL_V2
from pygerduty.common import Requester


Expand Down Expand Up @@ -35,3 +37,23 @@ def test_create_event():

assert response == 'srv01/HTTP'


@httpretty.activate
def test_enqueue_event_v2():
response = {
"status": "success",
"message": "Event processed",
"dedup_key": "Service (P123456) Test Dedup Key"
}
httpretty.register_uri(
httpretty.POST, INTEGRATION_API_URL_V2,
body=textwrap.dedent(json.dumps(response)), status=200)

E = pygerduty.events_v2.Events('fake_integration_key')

request = {}
with open('tests/fixtures/event_request_v2.json') as fp:
request = json.load(fp)

dedup_key = E.enqueue(**request)
assert dedup_key == response['dedup_key']
17 changes: 17 additions & 0 deletions tests/fixtures/event_request_v2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"event_action": "trigger",
"payload": {
"custom_details": {
"Service Name": "Test Service",
"Problem": "Something explanation",
"Service ID": "P123456",
"Result": "Error testing occurred"
},
"severity": "error",
"component": "Test Component",
"summary": "Service (P123456) Test Error",
"source": "Test Source",
"class": "Unit Test"
},
"dedup_key": "Service (P123456) Test Dedup Key"
}