This is an automated email from the ASF dual-hosted git repository.
eladkal pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 30faf4a87a Add send_event method in PagerdutyEventsHook (#31290)
30faf4a87a is described below
commit 30faf4a87a2e1b32de36f130aea5877d5e1003c6
Author: Utkarsh Sharma <[email protected]>
AuthorDate: Tue May 23 10:46:49 2023 +0530
Add send_event method in PagerdutyEventsHook (#31290)
* Add send_event method in PagerdutyEventsHook
send_event() methods is suppose to replace PagerdutyEventsHook's
create_event() method. Within send_event() we are using PagerdutySDK's
send_event() instead of post() which is specific to our requirment. Also added
deprecation warning in send_event() method
---
.../providers/pagerduty/hooks/pagerduty_events.py | 116 +++++++++++++++++++--
.../pagerduty/hooks/test_pagerduty_events.py | 32 ++++++
2 files changed, 140 insertions(+), 8 deletions(-)
diff --git a/airflow/providers/pagerduty/hooks/pagerduty_events.py
b/airflow/providers/pagerduty/hooks/pagerduty_events.py
index c86790bbd7..81607e4c93 100644
--- a/airflow/providers/pagerduty/hooks/pagerduty_events.py
+++ b/airflow/providers/pagerduty/hooks/pagerduty_events.py
@@ -18,12 +18,13 @@
"""Hook for sending or receiving data from PagerDuty as well as creating
PagerDuty incidents."""
from __future__ import annotations
+import warnings
from datetime import datetime
from typing import Any
import pdpyras
-from airflow.exceptions import AirflowException
+from airflow.exceptions import AirflowException,
AirflowProviderDeprecationWarning
from airflow.hooks.base import BaseHook
@@ -115,6 +116,108 @@ class PagerdutyEventsHook(BaseHook):
link's text.
:return: PagerDuty Events API v2 response.
"""
+ warnings.warn(
+ "This method will be deprecated. Please use the "
+ "`PagerdutyEventsHook.send_event` to interact with the Events API",
+ AirflowProviderDeprecationWarning,
+ stacklevel=1,
+ )
+
+ data = PagerdutyEventsHook.prepare_event_data(
+ summary=summary,
+ severity=severity,
+ source=source,
+ custom_details=custom_details,
+ component=component,
+ group=group,
+ class_type=class_type,
+ action=action,
+ dedup_key=dedup_key,
+ images=images,
+ links=links,
+ action_key_name="event_action",
+ )
+
+ session = pdpyras.EventsAPISession(self.integration_key)
+ resp = session.post("/v2/enqueue", json=data)
+ resp.raise_for_status()
+ return resp.json()
+
+ def send_event(
+ self,
+ summary: str,
+ severity: str,
+ source: str = "airflow",
+ action: str = "trigger",
+ dedup_key: str | None = None,
+ custom_details: Any | None = None,
+ group: str | None = None,
+ component: str | None = None,
+ class_type: str | None = None,
+ images: list[Any] | None = None,
+ links: list[Any] | None = None,
+ ) -> dict:
+ """
+ Create event for service integration.
+
+ :param summary: Summary for the event
+ :param severity: Severity for the event, needs to be one of: info,
warning, error, critical
+ :param source: Specific human-readable unique identifier, such as a
+ hostname, for the system having the problem.
+ :param action: Event action, needs to be one of: trigger, acknowledge,
+ resolve. Default to trigger if not specified.
+ :param dedup_key: A string which identifies the alert triggered for
the given event.
+ Required for the actions acknowledge and resolve.
+ :param custom_details: Free-form details from the event. Can be a
dictionary or a string.
+ If a dictionary is passed it will show up in PagerDuty as a table.
+ :param group: A cluster or grouping of sources. For example, sources
+ "prod-datapipe-02" and "prod-datapipe-03" might both be part of
"prod-datapipe"
+ :param component: The part or component of the affected system that is
broken.
+ :param class_type: The class/type of the event.
+ :param images: List of images to include. Each dictionary in the list
accepts the following keys:
+ `src`: The source (URL) of the image being attached to the
incident. This image must be served via
+ HTTPS.
+ `href`: [Optional] URL to make the image a clickable link.
+ `alt`: [Optional] Alternative text for the image.
+ :param links: List of links to include. Each dictionary in the list
accepts the following keys:
+ `href`: URL of the link to be attached.
+ `text`: [Optional] Plain text that describes the purpose of the
link, and can be used as the
+ link's text.
+ :return: PagerDuty Events API v2 response.
+ """
+ data = PagerdutyEventsHook.prepare_event_data(
+ summary=summary,
+ severity=severity,
+ source=source,
+ custom_details=custom_details,
+ component=component,
+ group=group,
+ class_type=class_type,
+ action=action,
+ dedup_key=dedup_key,
+ images=images,
+ links=links,
+ )
+
+ session = pdpyras.EventsAPISession(self.integration_key)
+ return session.send_event(**data)
+
+ @staticmethod
+ def prepare_event_data(
+ summary,
+ severity,
+ source,
+ custom_details,
+ component,
+ group,
+ class_type,
+ action,
+ dedup_key,
+ images,
+ links,
+ action_key_name: str = "action",
+ ) -> dict:
+ """Prepare event data for send_event / post('/v2/enqueue') method."""
payload = {
"summary": summary,
"severity": severity,
@@ -133,25 +236,22 @@ class PagerdutyEventsHook(BaseHook):
if action not in actions:
raise ValueError(f"Event action must be one of: {',
'.join(actions)}")
data = {
- "event_action": action,
+ action_key_name: action,
"payload": payload,
}
if dedup_key:
data["dedup_key"] = dedup_key
elif action != "trigger":
raise ValueError(
- f"The dedup_key property is required for event_action={action}
events, "
- f"and it must be a string."
+ f"The dedup_key property is required for
{action_key_name}={action} events,"
+ f" and it must be a string."
)
if images is not None:
data["images"] = images
if links is not None:
data["links"] = links
- session = pdpyras.EventsAPISession(self.integration_key)
- resp = session.post("/v2/enqueue", json=data)
- resp.raise_for_status()
- return resp.json()
+ return data
def create_change_event(
self,
diff --git a/tests/providers/pagerduty/hooks/test_pagerduty_events.py
b/tests/providers/pagerduty/hooks/test_pagerduty_events.py
index 7ba86d25db..41e1920813 100644
--- a/tests/providers/pagerduty/hooks/test_pagerduty_events.py
+++ b/tests/providers/pagerduty/hooks/test_pagerduty_events.py
@@ -19,6 +19,7 @@ from __future__ import annotations
import pytest
+from airflow.exceptions import AirflowProviderDeprecationWarning
from airflow.models import Connection
from airflow.providers.pagerduty.hooks.pagerduty import PagerdutyEventsHook
from airflow.utils import db
@@ -62,3 +63,34 @@ class TestPagerdutyEventsHook:
requests_mock.post("https://events.pagerduty.com/v2/change/enqueue",
json=mock_response_body)
resp = hook.create_change_event(summary="test", source="airflow")
assert resp == change_event_id
+
+ def test_send_event(self, requests_mock, events_connections):
+ hook = PagerdutyEventsHook(pagerduty_events_conn_id=DEFAULT_CONN_ID)
+ dedup_key = "samplekeyhere"
+ mock_response_body = {
+ "status": "success",
+ "message": "Event processed",
+ "dedup_key": dedup_key,
+ }
+ requests_mock.post("https://events.pagerduty.com/v2/enqueue",
json=mock_response_body)
+ resp = hook.send_event(summary="test", source="airflow_test",
severity="error", dedup_key=dedup_key)
+ assert resp == dedup_key
+
+ def test_create_event_deprecation_warning(self, requests_mock,
events_connections):
+ hook = PagerdutyEventsHook(pagerduty_events_conn_id=DEFAULT_CONN_ID)
+ mock_response_body = {
+ "status": "success",
+ "message": "Event processed",
+ "dedup_key": "samplekeyhere",
+ }
+ requests_mock.post("https://events.pagerduty.com/v2/enqueue",
json=mock_response_body)
+ warning = (
+ "This method will be deprecated. Please use the
`PagerdutyEventsHook.send_event`"
+ " to interact with the Events API"
+ )
+ with pytest.warns(AirflowProviderDeprecationWarning, match=warning):
+ hook.create_event(
+ summary="test",
+ source="airflow_test",
+ severity="error",
+ )