Skip to content

Commit cd12ce4

Browse files
authored
feat(scheduler-targets): eventBridge putEvents target (#27629)
An eventBridgePutEvents target was implemented similar to the already existing LambdaInvoke/StepFunctionStartExecution target. I needed to change some properties and methods from Target.ts from private to protected so that the logic could be reused (hope that is ok). Some design choices to outline (let me know if you disagree or have improvements I could take :) ): 1. PutEvents would accept multiple Entries (eg. an array), but I decided to support just one single event, because how Target is currently designed (to support only one target arn). It also aligns with the templated integration in the aws management console. 2. It throws an error in the constructor if the base prop `input` is used. All the props should be delivered by the new `EventBridgePutEventsEntry`. It felt not right for the developer experience to split the object (detail to `input` and `source`, `detailType` to `EventBridgePutEventsEntry` ). Closes #27454. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 1a586f2 commit cd12ce4

15 files changed

+36058
-3
lines changed

packages/@aws-cdk/aws-scheduler-targets-alpha/README.md

+28
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ The following targets are supported:
2929
3. `targets.CodeBuildStartBuild`: [Start a CodeBuild job](#start-a-codebuild-job)
3030
4. `targets.SqsSendMessage`: [Send a Message to an Amazon SQS Queue](#send-a-message-to-sqs-queue)
3131
5. `targets.SnsPublish`: [Publish messages to an Amazon SNS topic](#publish-messages-to-an-amazon-sns-topic)
32+
6. `targets.EventBridgePutEvents`: [Put Events on EventBridge](#send-events-to-an-eventbridge-event-bus)
3233

3334
## Invoke a Lambda function
3435

@@ -178,3 +179,30 @@ new Schedule(this, 'Schedule', {
178179
target,
179180
});
180181
```
182+
183+
## Send events to an EventBridge event bus
184+
185+
Use the `EventBridgePutEvents` target to send events to an EventBridge event bus.
186+
187+
The code snippet below creates an event rule with an EventBridge event bus as a target
188+
called every hour by Event Bridge Scheduler with a custom event payload.
189+
190+
```ts
191+
import * as events from 'aws-cdk-lib/aws-events';
192+
193+
const eventBus = new events.EventBus(this, 'EventBus', {
194+
eventBusName: 'DomainEvents',
195+
});
196+
197+
const eventEntry: targets.EventBridgePutEventsEntry = {
198+
eventBus,
199+
source: 'PetService',
200+
detail: ScheduleTargetInput.fromObject({ Name: 'Fluffy' }),
201+
detailType: '🐶',
202+
};
203+
204+
new Schedule(this, 'Schedule', {
205+
schedule: ScheduleExpression.rate(Duration.hours(1)),
206+
target: new targets.EventBridgePutEvents(eventEntry, {}),
207+
});
208+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { IScheduleTarget, ISchedule, ScheduleTargetInput, ScheduleTargetConfig } from '@aws-cdk/aws-scheduler-alpha';
2+
import { Names } from 'aws-cdk-lib';
3+
import * as events from 'aws-cdk-lib/aws-events';
4+
import { IRole } from 'aws-cdk-lib/aws-iam';
5+
import { ScheduleTargetBase, ScheduleTargetBaseProps } from './target';
6+
import { sameEnvDimension } from './util';
7+
8+
/**
9+
* An entry to be sent to EventBridge
10+
*
11+
* @see https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEventsRequestEntry.html
12+
*/
13+
export interface EventBridgePutEventsEntry {
14+
/**
15+
* The event body
16+
*
17+
* Can either be provided as an object or as a JSON-serialized string
18+
* @example
19+
*
20+
* ScheduleTargetInput.fromText('{"instance-id": "i-1234567890abcdef0", "state": "terminated"}');
21+
* ScheduleTargetInput.fromObject({ Message: 'Hello from a friendly event :)' });
22+
*/
23+
readonly detail: ScheduleTargetInput;
24+
25+
/**
26+
* Used along with the source field to help identify the fields and values expected in the detail field
27+
*
28+
* For example, events by CloudTrail have detail type "AWS API Call via CloudTrail"
29+
* @see https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events.html
30+
*/
31+
readonly detailType: string;
32+
33+
/**
34+
* The event bus the entry will be sent to.
35+
*
36+
*/
37+
readonly eventBus: events.IEventBus;
38+
39+
/**
40+
* The service or application that caused this event to be generated
41+
*
42+
* Example value: `com.example.service`
43+
*
44+
* @see https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events.html
45+
*/
46+
readonly source: string;
47+
}
48+
49+
/**
50+
* Send an event to an AWS EventBridge by AWS EventBridge Scheduler.
51+
*/
52+
export class EventBridgePutEvents extends ScheduleTargetBase implements IScheduleTarget {
53+
constructor(
54+
private readonly entry: EventBridgePutEventsEntry,
55+
private readonly props: ScheduleTargetBaseProps,
56+
) {
57+
super(props, entry.eventBus.eventBusArn);
58+
if (this.props.input) {
59+
throw new Error('ScheduleTargetBaseProps.input is not supported for EventBridgePutEvents. Please use entry.detail instead.');
60+
}
61+
}
62+
63+
protected addTargetActionToRole(schedule: ISchedule, role: IRole): void {
64+
const eventBus = this.entry.eventBus;
65+
const eventBusEnv = eventBus.env;
66+
if (!sameEnvDimension(eventBusEnv.region, schedule.env.region)) {
67+
throw new Error(`Cannot assign eventBus in region ${eventBusEnv.region} to the schedule ${Names.nodeUniqueId(schedule.node)} in region ${schedule.env.region}. Both the schedule and the eventBus must be in the same region.`);
68+
}
69+
70+
if (!sameEnvDimension(eventBusEnv.account, schedule.env.account)) {
71+
throw new Error(`Cannot assign eventBus in account ${eventBusEnv.account} to the schedule ${Names.nodeUniqueId(schedule.node)} in account ${schedule.env.region}. Both the schedule and the eventBus must be in the same account.`);
72+
}
73+
74+
if (this.props.role && !sameEnvDimension(this.props.role.env.account, eventBusEnv.account)) {
75+
throw new Error(`Cannot grant permission to execution role in account ${this.props.role.env.account} to invoke target ${Names.nodeUniqueId(eventBus.node)} in account ${eventBusEnv.account}. Both the target and the execution role must be in the same account.`);
76+
}
77+
78+
eventBus.grantPutEventsTo(role);
79+
}
80+
81+
protected bindBaseTargetConfig(_schedule: ISchedule): ScheduleTargetConfig {
82+
return {
83+
...super.bindBaseTargetConfig(_schedule),
84+
input: this.entry.detail,
85+
eventBridgeParameters: {
86+
detailType: this.entry.detailType,
87+
source: this.entry.source,
88+
},
89+
};
90+
}
91+
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from './codebuild-start-build';
2+
export * from './event-bridge-put-events';
3+
export * from './target';
24
export * from './lambda-invoke';
35
export * from './sns-publish';
4-
export * from './sqs-send-message';
56
export * from './stepfunctions-start-execution';
6-
export * from './target';
7+
export * from './sqs-send-message';

packages/@aws-cdk/aws-scheduler-targets-alpha/lib/target.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export abstract class ScheduleTargetBase {
9797
/**
9898
* Create a return a Schedule Target Configuration for the given schedule
9999
* @param schedule
100-
* @returnn
100+
* @returns a Schedule Target Configuration
101101
*/
102102
bind(schedule: ISchedule): ScheduleTargetConfig {
103103
return this.bindBaseTargetConfig(schedule);

0 commit comments

Comments
 (0)