Skip to content

Commit

Permalink
refactor(events): clean up Events APIs (#2840)
Browse files Browse the repository at this point in the history
Biggest change is modeling the schedule types.

BREAKING CHANGE:

* **events**: `EventPattern.detail` is now a map.
* **events**: `scheduleExpression: string` is now `schedule: Schedule`.
  • Loading branch information
rix0rrr authored Jun 18, 2019
1 parent d017a14 commit 1e23921
Show file tree
Hide file tree
Showing 23 changed files with 249 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface ScheduledEc2TaskProps {
*
* @see http://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html
*/
readonly scheduleExpression: string;
readonly schedule: events.Schedule;

/**
* The CMD value to pass to the container. A string with commands delimited by commas.
Expand Down Expand Up @@ -106,7 +106,7 @@ export class ScheduledEc2Task extends cdk.Construct {

// An EventRule that describes the event trigger (in this case a scheduled run)
const eventRule = new events.Rule(this, 'ScheduledEventRule', {
scheduleExpression: props.scheduleExpression,
schedule: props.schedule,
});
eventRule.addTarget(eventRuleTarget);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ec2 = require('@aws-cdk/aws-ec2');
import ecs = require('@aws-cdk/aws-ecs');
import events = require('@aws-cdk/aws-events');
import cdk = require('@aws-cdk/cdk');

import { ScheduledEc2Task } from '../../lib';
Expand All @@ -26,7 +27,7 @@ class EventStack extends cdk.Stack {
memoryLimitMiB: 512,
cpu: 1,
environment: { name: 'TRIGGER', value: 'CloudWatch Events' },
scheduleExpression: 'rate(1 minute)'
schedule: events.Schedule.rate(1, events.TimeUnit.Minute),
});
/// !hide
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { expect, haveResource } from '@aws-cdk/assert';
import ec2 = require('@aws-cdk/aws-ec2');
import ecs = require('@aws-cdk/aws-ecs');
import events = require('@aws-cdk/aws-events');
import cdk = require('@aws-cdk/cdk');
import { Test } from 'nodeunit';
import { ScheduledEc2Task } from '../../lib';
Expand All @@ -19,7 +20,7 @@ export = {
cluster,
image: ecs.ContainerImage.fromRegistry('henk'),
memoryLimitMiB: 512,
scheduleExpression: 'rate(1 minute)'
schedule: events.Schedule.expression('rate(1 minute)')
});

// THEN
Expand Down Expand Up @@ -85,7 +86,7 @@ export = {
memoryLimitMiB: 512,
cpu: 2,
environment: { name: 'TRIGGER', value: 'CloudWatch Events' },
scheduleExpression: 'rate(1 minute)'
schedule: events.Schedule.expression('rate(1 minute)')
});

// THEN
Expand Down Expand Up @@ -159,7 +160,7 @@ export = {
cluster,
image: ecs.ContainerImage.fromRegistry('henk'),
memoryReservationMiB: 512,
scheduleExpression: 'rate(1 minute)'
schedule: events.Schedule.expression('rate(1 minute)')
});

// THEN
Expand Down Expand Up @@ -208,7 +209,7 @@ export = {
image: ecs.ContainerImage.fromRegistry('henk'),
memoryReservationMiB: 512,
command: ["-c", "4", "amazon.com"],
scheduleExpression: 'rate(1 minute)'
schedule: events.Schedule.expression('rate(1 minute)')
});

// THEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ test('use codebuild project as an eventrule target', () => {
// GIVEN
const stack = new Stack();
const project = new codebuild.PipelineProject(stack, 'MyProject');
const rule = new events.Rule(stack, 'Rule', { scheduleExpression: 'rate(1 min)' });
const rule = new events.Rule(stack, 'Rule', {
schedule: events.Schedule.expression('rate(1 min)')
});

// WHEN
rule.addTarget(new targets.CodeBuildProject(project));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pipeline.addStage({
});

new events.Rule(stack, 'rule', {
scheduleExpression: 'rate(1 minute)',
schedule: events.Schedule.expression('rate(1 minute)'),
targets: [new targets.CodePipeline(pipeline)]
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ test('use codebuild project as an eventrule target', () => {
artifactBounds: { minInputs: 1, maxInputs: 1 , minOutputs: 1, maxOutputs: 1, }})]
});

const rule = new events.Rule(stack, 'rule', { scheduleExpression: 'rate(1 min)' });
const rule = new events.Rule(stack, 'rule', {
schedule: events.Schedule.expression('rate(1 minute)'),
});

// WHEN
rule.addTarget(new targets.CodePipeline(pipeline));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ test("Can use EC2 taskdef as EventRule target", () => {
});

const rule = new events.Rule(stack, 'Rule', {
scheduleExpression: 'rate(1 minute)',
schedule: events.Schedule.expression('rate(1 min)')
});

// WHEN
Expand Down Expand Up @@ -69,7 +69,7 @@ test("Can use Fargate taskdef as EventRule target", () => {
});

const rule = new events.Rule(stack, 'Rule', {
scheduleExpression: 'rate(1 minute)',
schedule: events.Schedule.expression('rate(1 min)')
});

// WHEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class EventStack extends cdk.Stack {

// An Rule that describes the event trigger (in this case a scheduled run)
const rule = new events.Rule(this, 'Rule', {
scheduleExpression: 'rate(1 minute)',
schedule: events.Schedule.rate(1, events.TimeUnit.Minute),
});

// Use EcsTask as the target of the Rule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class EventStack extends cdk.Stack {

// A rule that describes the event trigger (in this case a scheduled run)
const rule = new events.Rule(this, 'Rule', {
scheduleExpression: 'rate(1 minute)',
schedule: events.Schedule.rate(1, events.TimeUnit.Minute),
});

// Use EcsTask as the target of the Rule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ const fn = new lambda.Function(stack, 'MyFunc', {
code: lambda.Code.inline(`exports.handler = ${handler.toString()}`)
});

const timer = new events.Rule(stack, 'Timer', { scheduleExpression: 'rate(1 minute)' });
const timer = new events.Rule(stack, 'Timer', {
schedule: events.Schedule.rate(1, events.TimeUnit.Minute),
});
timer.addTarget(new targets.LambdaFunction(fn));

const timer2 = new events.Rule(stack, 'Timer2', { scheduleExpression: 'rate(2 minutes)' });
const timer2 = new events.Rule(stack, 'Timer2', {
schedule: events.Schedule.rate(2, events.TimeUnit.Minute),
});
timer2.addTarget(new targets.LambdaFunction(fn));

app.synth();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ test('use lambda as an event rule target', () => {
// GIVEN
const stack = new cdk.Stack();
const fn = newTestLambda(stack);
const rule1 = new events.Rule(stack, 'Rule', { scheduleExpression: 'rate(1 minute)' });
const rule2 = new events.Rule(stack, 'Rule2', { scheduleExpression: 'rate(5 minutes)' });
const rule1 = new events.Rule(stack, 'Rule', {
schedule: events.Schedule.rate(1, events.TimeUnit.Minute),
});
const rule2 = new events.Rule(stack, 'Rule2', {
schedule: events.Schedule.rate(5, events.TimeUnit.Minute),
});

// WHEN
rule1.addTarget(new targets.LambdaFunction(fn));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const stack = new cdk.Stack(app, 'aws-cdk-sns-event-target');

const topic = new sns.Topic(stack, 'MyTopic');
const event = new events.Rule(stack, 'EveryMinute', {
scheduleExpression: 'rate(1 minute)'
schedule: events.Schedule.rate(1, events.TimeUnit.Minute),
});

const queue = new sqs.Queue(stack, 'MyQueue');
Expand Down
6 changes: 4 additions & 2 deletions packages/@aws-cdk/aws-events-targets/test/sns/sns.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ test('sns topic as an event rule target', () => {
const stack = new Stack();
const topic = new sns.Topic(stack, 'MyTopic');
const rule = new events.Rule(stack, 'MyRule', {
scheduleExpression: 'rate(1 hour)',
schedule: events.Schedule.rate(1, events.TimeUnit.Hour),
});

// WHEN
Expand Down Expand Up @@ -51,7 +51,9 @@ test('multiple uses of a topic as a target results in a single policy statement'

// WHEN
for (let i = 0; i < 5; ++i) {
const rule = new events.Rule(stack, `Rule${i}`, { scheduleExpression: 'rate(1 hour)' });
const rule = new events.Rule(stack, `Rule${i}`, {
schedule: events.Schedule.rate(1, events.TimeUnit.Hour),
});
rule.addTarget(new targets.SnsTopic(topic));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-cdk-sqs-event-target');

const event = new events.Rule(stack, 'MyRule', {
scheduleExpression: 'rate(1 minute)',
schedule: events.Schedule.rate(1, events.TimeUnit.Minute),
});

const queue = new sqs.Queue(stack, 'MyQueue');
Expand Down
6 changes: 4 additions & 2 deletions packages/@aws-cdk/aws-events-targets/test/sqs/sqs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ test('sns topic as an event rule target', () => {
const stack = new Stack();
const queue = new sqs.Queue(stack, 'MyQueue');
const rule = new events.Rule(stack, 'MyRule', {
scheduleExpression: 'rate(1 hour)',
schedule: events.Schedule.rate(1, events.TimeUnit.Hour),
});

// WHEN
Expand Down Expand Up @@ -74,7 +74,9 @@ test('multiple uses of a queue as a target results in multi policy statement bec

// WHEN
for (let i = 0; i < 2; ++i) {
const rule = new events.Rule(stack, `Rule${i}`, { scheduleExpression: 'rate(1 hour)' });
const rule = new events.Rule(stack, `Rule${i}`, {
schedule: events.Schedule.rate(1, events.TimeUnit.Hour),
});
rule.addTarget(new targets.SqsQueue(queue));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ test('State machine can be used as Event Rule target', () => {
// GIVEN
const stack = new cdk.Stack();
const rule = new events.Rule(stack, 'Rule', {
scheduleExpression: 'rate(1 minute)'
schedule: events.Schedule.rate(1, events.TimeUnit.Minute),
});
const stateMachine = new sfn.StateMachine(stack, 'SM', {
definition: new sfn.Wait(stack, 'Hello', { duration: sfn.WaitDuration.seconds(10) })
Expand Down
19 changes: 18 additions & 1 deletion packages/@aws-cdk/aws-events/lib/event-pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@
export interface EventPattern {
/**
* By default, this is set to 0 (zero) in all events.
*
* @default - No filtering on version
*/
readonly version?: string[];

/**
* A unique value is generated for every event. This can be helpful in
* tracing events as they move through rules to targets, and are processed.
*
* @default - No filtering on id
*/
readonly id?: string[];

Expand All @@ -44,6 +48,8 @@ export interface EventPattern {
* that appear in the detail field.
*
* Represents the "detail-type" event field.
*
* @default - No filtering on detail type
*/
readonly detailType?: string[];

Expand All @@ -58,11 +64,14 @@ export interface EventPattern {
* CloudFront is aws.cloudfront.
*
* @see http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-aws-service-namespaces
* @default - No filtering on source
*/
readonly source?: string[];

/**
* The 12-digit number identifying an AWS account.
*
* @default - No filtering on account
*/
readonly account?: string[];

Expand All @@ -71,11 +80,15 @@ export interface EventPattern {
* the event. If the event spans a time interval, the service might choose
* to report the start time, so this value can be noticeably before the time
* the event is actually received.
*
* @default - No filtering on time
*/
readonly time?: string[];

/**
* Identifies the AWS region where the event originated.
*
* @default - No filtering on region
*/
readonly region?: string[];

Expand All @@ -88,12 +101,16 @@ export interface EventPattern {
* instance ARNs, Auto Scaling events include ARNs for both instances and
* Auto Scaling groups, but API calls with AWS CloudTrail do not include
* resource ARNs.
*
* @default - No filtering on resource
*/
readonly resources?: string[];

/**
* A JSON object, whose content is at the discretion of the service
* originating the event.
*
* @default - No filtering on detail
*/
readonly detail?: any;
readonly detail?: {[key: string]: any};
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-events/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './rule';
export * from './rule-ref';
export * from './target';
export * from './event-pattern';
export * from './schedule';
export * from './on-event-options';

// AWS::Events CloudFormation Resources:
Expand Down
7 changes: 4 additions & 3 deletions packages/@aws-cdk/aws-events/lib/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Construct, Lazy, Resource } from '@aws-cdk/cdk';
import { EventPattern } from './event-pattern';
import { CfnRule } from './events.generated';
import { IRule } from './rule-ref';
import { Schedule } from './schedule';
import { IRuleTarget } from './target';
import { mergeEventPattern } from './util';

Expand Down Expand Up @@ -39,7 +40,7 @@ export interface RuleProps {
*
* @default - None.
*/
readonly scheduleExpression?: string;
readonly schedule?: Schedule;

/**
* Describes which events CloudWatch Events routes to the specified target.
Expand Down Expand Up @@ -104,7 +105,7 @@ export class Rule extends Resource implements IRule {
this.ruleArn = resource.attrArn;

this.addEventPattern(props.eventPattern);
this.scheduleExpression = props.scheduleExpression;
this.scheduleExpression = props.schedule && props.schedule.expressionString;

for (const target of props.targets || []) {
this.addTarget(target);
Expand Down Expand Up @@ -189,7 +190,7 @@ export class Rule extends Resource implements IRule {

protected validate() {
if (Object.keys(this.eventPattern).length === 0 && !this.scheduleExpression) {
return [ `Either 'eventPattern' or 'scheduleExpression' must be defined` ];
return [ `Either 'eventPattern' or 'schedule' must be defined` ];
}

return [ ];
Expand Down
Loading

0 comments on commit 1e23921

Please sign in to comment.