-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #72 from vincentclaes/71-implement-notification
71 implement notification
- Loading branch information
Showing
10 changed files
with
396 additions
and
588 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -269,6 +269,23 @@ some_task >> ... | |
|
||
</details> | ||
|
||
<details> | ||
<summary>Notify in case of error/success.</summary> | ||
|
||
Provide the parameter `notification` in the constructor of a `StepfunctionsWorkflow` object. | ||
This will create an SNS Topic which will be triggered in case of failure or success. | ||
The email will subscribe to the topic and receive the notification in its inbox. | ||
|
||
```python | ||
with StepfunctionsWorkflow(datajob_stack=datajob_stack, | ||
name="workflow", | ||
notification="[email protected]") as sfn: | ||
task1 >> task2 | ||
``` | ||
|
||
You can provide 1 email or a list of emails `["[email protected]", "[email protected]"]`. | ||
|
||
</details> | ||
|
||
# Datajob in depth | ||
|
||
|
@@ -348,7 +365,6 @@ These are the ideas, we find interesting to implement; | |
- add a time based trigger to the step functions workflow. | ||
- add an s3 event trigger to the step functions workflow. | ||
- add a lambda that copies data from one s3 location to another. | ||
- add an sns that notifies in case of any failure (slack/email) | ||
- version your data pipeline. | ||
- cli command to view the logs / glue jobs / s3 bucket | ||
- implement sagemaker services | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
from typing import Union | ||
|
||
from datajob.datajob_base import DataJobBase | ||
from aws_cdk import core | ||
from aws_cdk import aws_sns | ||
from aws_cdk import aws_sns_subscriptions | ||
from aws_cdk.core import Arn, ArnComponents | ||
|
||
|
||
class SnsTopic(DataJobBase): | ||
def __init__( | ||
self, | ||
datajob_stack: core.Construct, | ||
name: str, | ||
notification: Union[str, list], | ||
**kwargs | ||
): | ||
""" | ||
:param datajob_stack: aws cdk core construct object. | ||
:param name: name for the SNS Topic. | ||
:param notification: email address as string or list of email addresses to be subscribed. | ||
:param kwargs: | ||
""" | ||
super().__init__(datajob_stack, name, **kwargs) | ||
self.notification = notification | ||
self.sns_topic = None | ||
|
||
def create(self): | ||
self.sns_topic = aws_sns.Topic( | ||
scope=self, | ||
id=self.unique_name, | ||
display_name=self.unique_name, | ||
topic_name=self.unique_name, | ||
) | ||
self.add_email_subscription() | ||
|
||
def add_email_subscription(self) -> None: | ||
""" | ||
Add an email or a list of emails as subscribers to a topic. | ||
:param sns_topic: an SNS Topic instance of aws cdk | ||
:param notification: email address as string or list of email addresses to be subscribed. | ||
:return: None | ||
""" | ||
if isinstance(self.notification, list): | ||
for email in self.notification: | ||
self.sns_topic.add_subscription( | ||
aws_sns_subscriptions.EmailSubscription(email) | ||
) | ||
else: | ||
self.sns_topic.add_subscription( | ||
aws_sns_subscriptions.EmailSubscription(self.notification) | ||
) | ||
|
||
def get_topic_arn(self) -> str: | ||
""" | ||
The ARN will be formatted as follows: | ||
arn:{partition}:{service}:{region}:{account}:{resource}{sep}{resource-name} | ||
:return: return a well formatted arn string | ||
""" | ||
arn_components = ArnComponents( | ||
partition="aws", | ||
service="sns", | ||
region=self.datajob_stack.env.region, | ||
account=self.datajob_stack.env.account, | ||
resource=self.unique_name, | ||
) | ||
return Arn.format(components=arn_components, stack=self.datajob_stack) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
import json | ||
import os | ||
import unittest | ||
import io | ||
|
||
import yaml | ||
from aws_cdk import core | ||
from moto import mock_stepfunctions | ||
from stepfunctions.steps.compute import GlueStartJobRunStep | ||
|
@@ -82,7 +85,9 @@ def test_create_tasks_for_orchestration_starts_with_parallel_flow_successfully( | |
isinstance(a_step_functions_workflow.chain_of_tasks[1], GlueStartJobRunStep) | ||
) | ||
|
||
def test_orchestrate_1_task_successfully(self,): | ||
def test_orchestrate_1_task_successfully( | ||
self, | ||
): | ||
task1 = stepfunctions_workflow.task(SomeMockedClass("task1")) | ||
djs = DataJobStack( | ||
scope=self.app, | ||
|
@@ -98,3 +103,44 @@ def test_orchestrate_1_task_successfully(self,): | |
self.assertTrue( | ||
isinstance(a_step_functions_workflow.chain_of_tasks[0], GlueStartJobRunStep) | ||
) | ||
|
||
@mock_stepfunctions | ||
def test_create_workflow_with_notification_successfully(self): | ||
task1 = stepfunctions_workflow.task(SomeMockedClass("task1")) | ||
task2 = stepfunctions_workflow.task(SomeMockedClass("task2")) | ||
|
||
djs = DataJobStack( | ||
scope=self.app, | ||
id="a-unique-name-3", | ||
stage="stage", | ||
project_root="sampleproject/", | ||
region="eu-west-1", | ||
account="3098726354", | ||
) | ||
with StepfunctionsWorkflow( | ||
djs, "some-name", notification="[email protected]" | ||
) as a_step_functions_workflow: | ||
task1 >> task2 | ||
|
||
with io.StringIO() as f: | ||
f.write(a_step_functions_workflow.workflow.get_cloudformation_template()) | ||
f.seek(0) | ||
cf_template = yaml.load(f, Loader=yaml.FullLoader) | ||
|
||
sfn_workflow = json.loads( | ||
cf_template.get("Resources") | ||
.get("StateMachineComponent") | ||
.get("Properties") | ||
.get("DefinitionString") | ||
) | ||
# we expect two notifications; 1 for success and one for failure | ||
self.assertTrue("SuccessNotification" in sfn_workflow.get("States").keys()) | ||
self.assertTrue("FailureNotification" in sfn_workflow.get("States").keys()) | ||
# there is a catch statement in the statemachine | ||
self.assertTrue( | ||
"Catch" in sfn_workflow.get("States").get("notification").keys() | ||
) | ||
# when implementing a notification we expect a Parallel branch | ||
self.assertEqual( | ||
sfn_workflow.get("States").get("notification").get("Type"), "Parallel" | ||
) |
Oops, something went wrong.