Skip to content

Commit

Permalink
feat(scheduler-targets-alpha): SnsPublish scheduler target (aws#27838)
Browse files Browse the repository at this point in the history
Closes aws#27459 

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
ymhiroki authored and chenjane-dev committed Dec 5, 2023
1 parent 1cd58e0 commit 670fb61
Show file tree
Hide file tree
Showing 16 changed files with 35,916 additions and 4 deletions.
27 changes: 27 additions & 0 deletions packages/@aws-cdk/aws-scheduler-targets-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ The following targets are supported:
2. `targets.StepFunctionsStartExecution`: [Start an AWS Step Function](#start-an-aws-step-function)
3. `targets.CodeBuildStartBuild`: [Start a CodeBuild job](#start-a-codebuild-job)
4. `targets.SqsSendMessage`: [Send a Message to an Amazon SQS Queue](#send-a-message-to-sqs-queue)
5. `targets.SnsPublish`: [Publish messages to an Amazon SNS topic](#publish-messages-to-an-amazon-sns-topic)

## Invoke a Lambda function

Expand Down Expand Up @@ -151,3 +152,29 @@ new Schedule(this, 'Schedule', {
target
});
```

## Publish messages to an Amazon SNS topic

Use the `SnsPublish` target to publish messages to an Amazon SNS topic.

The code snippets below create create an event rule with a Amazon SNS topic as a target.
It's called every hour by Amazon Event Bridge Scheduler with custom payload.

```ts
import * as sns from 'aws-cdk-lib/aws-sns';

const topic = new sns.Topic(this, 'Topic');

const payload = {
message: 'Hello scheduler!',
};

const target = new targets.SnsPublish(topic, {
input: ScheduleTargetInput.fromObject(payload),
});

new Schedule(this, 'Schedule', {
schedule: ScheduleExpression.rate(Duration.hours(1)),
target,
});
```
7 changes: 4 additions & 3 deletions packages/@aws-cdk/aws-scheduler-targets-alpha/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './target';
export * from './lambda-invoke';
export * from './stepfunctions-start-execution';
export * from './codebuild-start-build';
export * from './lambda-invoke';
export * from './sns-publish';
export * from './sqs-send-message';
export * from './stepfunctions-start-execution';
export * from './target';
37 changes: 37 additions & 0 deletions packages/@aws-cdk/aws-scheduler-targets-alpha/lib/sns-publish.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ISchedule, IScheduleTarget } from '@aws-cdk/aws-scheduler-alpha';
import { Names } from 'aws-cdk-lib';
import { IRole } from 'aws-cdk-lib/aws-iam';
import * as sns from 'aws-cdk-lib/aws-sns';
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
import { sameEnvDimension } from './util';

/**
* Use an Amazon SNS topic as a target for AWS EventBridge Scheduler.
*/
export class SnsPublish extends ScheduleTargetBase implements IScheduleTarget {
constructor(
private readonly topic: sns.ITopic,
private readonly props: ScheduleTargetBaseProps = {},
) {
super(props, topic.topicArn);
}

protected addTargetActionToRole(schedule: ISchedule, role: IRole): void {
// Check if target and schedule are in the region
if (!sameEnvDimension(this.topic.env.region, schedule.env.region)) {
throw new Error(`Cannot assign topic in region ${this.topic.env.region} to the schedule ${Names.nodeUniqueId(schedule.node)} in region ${schedule.env.region}. Both the schedule and the topic must be in the same region.`);
}

// Check if target and schedule are in the same account
if (!sameEnvDimension(this.topic.env.account, schedule.env.account)) {
throw new Error(`Cannot assign topic in account ${this.topic.env.account} to the schedule ${Names.nodeUniqueId(schedule.node)} in account ${role.env.account}. Both the schedule and the topic must be in the same account.`);
}

// Check if target and role are in the same account
if (this.props.role && !sameEnvDimension(this.props.role.env.account, this.topic.env.account)) {
throw new Error(`Cannot grant permission to execution role in account ${this.props.role.env.account} to publish to target ${Names.nodeUniqueId(this.topic.node)} in account ${this.topic.env.account}. Both the target and the execution role must be in the same account.`);
}

this.topic.grantPublish(role);
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
{
"Resources": {
"TopicBFC7AF6E": {
"Type": "AWS::SNS::Topic"
},
"Queue4A7E3555": {
"Type": "AWS::SQS::Queue",
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete"
},
"QueuePolicy25439813": {
"Type": "AWS::SQS::QueuePolicy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "sqs:SendMessage",
"Condition": {
"ArnEquals": {
"aws:SourceArn": {
"Ref": "TopicBFC7AF6E"
}
}
},
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Resource": {
"Fn::GetAtt": [
"Queue4A7E3555",
"Arn"
]
}
}
],
"Version": "2012-10-17"
},
"Queues": [
{
"Ref": "Queue4A7E3555"
}
]
}
},
"QueueAwsSchedulerTargetsSnsPublishTopicCB9BF6E1C346AD60": {
"Type": "AWS::SNS::Subscription",
"Properties": {
"Endpoint": {
"Fn::GetAtt": [
"Queue4A7E3555",
"Arn"
]
},
"Protocol": "sqs",
"RawMessageDelivery": true,
"TopicArn": {
"Ref": "TopicBFC7AF6E"
}
},
"DependsOn": [
"QueuePolicy25439813"
]
},
"Schedule83A77FD1": {
"Type": "AWS::Scheduler::Schedule",
"Properties": {
"FlexibleTimeWindow": {
"Mode": "OFF"
},
"ScheduleExpression": "rate(1 minute)",
"ScheduleExpressionTimezone": "Etc/UTC",
"State": "ENABLED",
"Target": {
"Arn": {
"Ref": "TopicBFC7AF6E"
},
"Input": "\"Hello, Scheduler!\"",
"RetryPolicy": {
"MaximumEventAgeInSeconds": 86400,
"MaximumRetryAttempts": 185
},
"RoleArn": {
"Fn::GetAtt": [
"SchedulerRoleForTarget1441a743A31888",
"Arn"
]
}
}
}
},
"SchedulerRoleForTarget1441a743A31888": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"aws:SourceAccount": {
"Ref": "AWS::AccountId"
}
}
},
"Effect": "Allow",
"Principal": {
"Service": "scheduler.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"SchedulerRoleForTarget1441a7DefaultPolicy885B6BFD": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "sns:Publish",
"Effect": "Allow",
"Resource": {
"Ref": "TopicBFC7AF6E"
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "SchedulerRoleForTarget1441a7DefaultPolicy885B6BFD",
"Roles": [
{
"Ref": "SchedulerRoleForTarget1441a743A31888"
}
]
}
}
},
"Outputs": {
"ExportsOutputRefQueue4A7E3555425E8BD3": {
"Value": {
"Ref": "Queue4A7E3555"
},
"Export": {
"Name": "AwsSchedulerTargetsSnsPublish:ExportsOutputRefQueue4A7E3555425E8BD3"
}
}
},
"Parameters": {
"BootstrapVersion": {
"Type": "AWS::SSM::Parameter::Value<String>",
"Default": "/cdk-bootstrap/hnb659fds/version",
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
}
},
"Rules": {
"CheckBootstrapVersion": {
"Assertions": [
{
"Assert": {
"Fn::Not": [
{
"Fn::Contains": [
[
"1",
"2",
"3",
"4",
"5"
],
{
"Ref": "BootstrapVersion"
}
]
}
]
},
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
}
]
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 670fb61

Please sign in to comment.