From 5a0843d2e9f11eed152c65b0ab5376474ad75a7d Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Wed, 3 May 2023 22:45:47 +0000 Subject: [PATCH 01/21] Add schedule expression implementation --- .../aws-cdk-lib/aws-scheduler/lib/index.ts | 3 +- .../aws-scheduler/lib/schedule-expression.ts | 104 +++++++++++ .../test/schedule-expression.test.ts | 165 ++++++++++++++++++ 3 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts create mode 100644 packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts diff --git a/packages/aws-cdk-lib/aws-scheduler/lib/index.ts b/packages/aws-cdk-lib/aws-scheduler/lib/index.ts index ae3df1e12b699..54b160ae64354 100644 --- a/packages/aws-cdk-lib/aws-scheduler/lib/index.ts +++ b/packages/aws-cdk-lib/aws-scheduler/lib/index.ts @@ -1 +1,2 @@ -export * from './scheduler.generated'; \ No newline at end of file +export * from './scheduler.generated'; +export * from './schedule-expression'; \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts b/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts new file mode 100644 index 0000000000000..6548bac866507 --- /dev/null +++ b/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts @@ -0,0 +1,104 @@ +import { Construct } from 'constructs'; +import * as events from '../../aws-events'; +import { CronOptions } from '../../aws-events'; +import { Duration, TimeZone } from '../../core'; + + +/** + * ScheduleExpression for EventBridge Schedule + * + * You can choose from three schedule types when configuring your schedule: rate-based, cron-based, and one-time schedules. + * Both rate-based and cron-based schedules are recurring schedules. + * + * @see https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html + */ +export abstract class ScheduleExpression { + + + /** + * Construct a one-time schedule from a date. + * + * @param date The date and time to use. The millisecond part will be ignored. + * @param timeZone The time zone to use for interpreting the date. Default: - UTC + */ + public static at(date: Date, timeZone?: TimeZone): ScheduleExpression { + try { + const literal = date.toISOString().split('.')[0]; + return new LiteralScheduleExpression(`at(${literal})`, timeZone ?? TimeZone.ETC_UTC); + } catch (e) { + if (e instanceof RangeError) { + throw new Error('Invalid date'); + } + throw e; + } + } + + /** + * Construct a schedule from a literal schedule expression + * @param expression The expression to use. Must be in a format that EventBridge will recognize + * @param timeZone The time zone to use for interpreting the expression. Default: - UTC + */ + public static expression(expression: string, timeZone?: TimeZone): ScheduleExpression { + return new LiteralScheduleExpression(expression, timeZone ?? TimeZone.ETC_UTC); + } + + /** + * Construct a recurring schedule from an interval and a time unit + * + * Rates may be defined with any unit of time, but when converted into minutes, the duration must be a positive whole number of minutes. + */ + static rate(duration: Duration): ScheduleExpression { + const schedule = events.Schedule.rate(duration); + return new LiteralScheduleExpression(schedule.expressionString); + } + + /** + * Create a srecurring chedule from a set of cron fields and time zone. + */ + static cron(options: CronOptionsWithTimezone): ScheduleExpression { + const schedule = events.Schedule.cron(options); + return new LiteralScheduleExpression(schedule.expressionString, options.timeZone ?? TimeZone.ETC_UTC); + } + + /** + * Retrieve the expression for this schedule + */ + public abstract readonly expressionString: string; + /** + * Retrieve the expression for this schedule + */ + public abstract readonly timeZone?: TimeZone; + + protected constructor() {}; + /** + * + * @internal + */ + abstract _bind(scope: Construct): void; +} + +/** + * Options to configure a cron expression + * + * All fields are strings so you can use complex expressions. Absence of + * a field implies '*' or '?', whichever one is appropriate. + * + * @see https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html#cron-expressions + */ +export interface CronOptionsWithTimezone extends CronOptions { + /** + * The timezone to run the schedule in + * + * @default - UTC + */ + readonly timeZone?: TimeZone; +} + +class LiteralScheduleExpression extends ScheduleExpression { + + constructor(public readonly expressionString: string, public readonly timeZone?: TimeZone) { + super(); + } + + public _bind() {} +} diff --git a/packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts b/packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts new file mode 100644 index 0000000000000..04c41a2e6c122 --- /dev/null +++ b/packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts @@ -0,0 +1,165 @@ +import { Duration, Stack, Lazy, TimeZone } from '../../core'; +import { ScheduleExpression } from '../lib'; + + +describe('schedule expression', () => { + test('cron expressions day and dow are mutex: given weekday', () => { + // Run every 10 minutes Monday through Friday + expect('cron(0/10 * ? * MON-FRI *)').toEqual(ScheduleExpression.cron({ + minute: '0/10', + weekDay: 'MON-FRI', + }).expressionString); + }); + + test('cron expressions day and dow are mutex: given month day', () => { + // Run at 8:00 am (UTC) every 1st day of the month + expect('cron(0 8 1 * ? *)').toEqual(ScheduleExpression.cron({ + minute: '0', + hour: '8', + day: '1', + }).expressionString); + }); + + test('cron expressions day and dow are mutex: given neither', () => { + // Run at 10:00 am (UTC) every day + expect('cron(0 10 * * ? *)').toEqual(ScheduleExpression.cron({ + minute: '0', + hour: '10', + }).expressionString); + }); + + test('cron expressions saves timezone', () => { + expect(TimeZone.EUROPE_LONDON).toEqual(ScheduleExpression.cron( + { + minute: '0', + hour: '10', + timeZone: TimeZone.EUROPE_LONDON, + }).timeZone); + }); + + test('cron expressions timezone is UTC if not specified', () => { + expect(TimeZone.ETC_UTC).toEqual(ScheduleExpression.cron( + { + minute: '0', + hour: '10', + }).timeZone); + }); + + test('rate cannot be 0', () => { + expect(() => { + ScheduleExpression.rate(Duration.days(0)); + }).toThrow(/Duration cannot be 0/); + }); + + test('rate cannot be negative', () => { + expect(() => { + ScheduleExpression.rate(Duration.minutes(-2)); + }).toThrow(/Duration amounts cannot be negative/); + }); + + test('rate can be from a token', () => { + const stack = new Stack(); + const lazyDuration = Duration.minutes(Lazy.number({ produce: () => 5 })); + const rate = ScheduleExpression.rate(lazyDuration); + expect('rate(5 minutes)').toEqual(stack.resolve(rate).expressionString); + }); + + test('rate can be in minutes', () => { + expect('rate(10 minutes)').toEqual( + ScheduleExpression.rate(Duration.minutes(10)) + .expressionString); + }); + + test('rate can be in days', () => { + expect('rate(10 days)').toEqual( + ScheduleExpression.rate(Duration.days(10)) + .expressionString); + }); + + test('rate can be in hours', () => { + expect('rate(10 hours)').toEqual( + ScheduleExpression.rate(Duration.hours(10)) + .expressionString); + }); + + test('rate can be in seconds', () => { + expect('rate(2 minutes)').toEqual( + ScheduleExpression.rate(Duration.seconds(120)) + .expressionString); + }); + + test('rate must not be in seconds when specified as a token', () => { + expect(() => { + ScheduleExpression.rate(Duration.seconds(Lazy.number({ produce: () => 5 }))); + }).toThrow(/Allowed units for scheduling/); + }); + + test('one-time expression string has expected date', () => { + const x = ScheduleExpression.at(new Date(2022, 10, 20, 19, 20, 23)); + expect(x.expressionString).toEqual('at(2022-11-20T19:20:23)'); + }); + + test('one-time expression time zone is UTC if not provided', () => { + const x = ScheduleExpression.at(new Date(2022, 10, 20, 19, 20, 23)); + expect(x.timeZone).toEqual(TimeZone.ETC_UTC); + }); + + test('one-time expression has expected time zone if provided', () => { + const x = ScheduleExpression.at(new Date(2022, 10, 20, 19, 20, 23), TimeZone.EUROPE_LONDON); + expect(x.expressionString).toEqual('at(2022-11-20T19:20:23)'); + expect(x.timeZone).toEqual(TimeZone.EUROPE_LONDON); + }); + + test('one-time expression milliseconds ignored', () => { + const x = ScheduleExpression.at(new Date(Date.UTC(2022, 10, 20, 19, 20, 23, 111))); + expect(x.expressionString).toEqual('at(2022-11-20T19:20:23)'); + }); + + test('one-time expression with invalid date throws', () => { + expect(() => ScheduleExpression.at(new Date('13-20-1969'))).toThrowError('Invalid date'); + }); +}); + +describe('fractional minutes checks', () => { + test('rate cannot be a fractional amount of minutes (defined with seconds)', () => { + expect(() => { + ScheduleExpression.rate(Duration.seconds(150)); + }).toThrow(/cannot be converted into a whole number of/); + }); + + test('rate cannot be a fractional amount of minutes (defined with minutes)', () => { + expect(()=> { + ScheduleExpression.rate(Duration.minutes(5/3)); + }).toThrow(/must be a whole number of/); + }); + + test('rate cannot be a fractional amount of minutes (defined with hours)', () => { + expect(()=> { + ScheduleExpression.rate(Duration.hours(1.03)); + }).toThrow(/cannot be converted into a whole number of/); + }); + + test('rate cannot be less than 1 minute (defined with seconds)', () => { + expect(() => { + ScheduleExpression.rate(Duration.seconds(30)); + }).toThrow(/'30 seconds' cannot be converted into a whole number of minutes./); + }); + + test('rate cannot be less than 1 minute (defined with minutes as fractions)', () => { + expect(() => { + ScheduleExpression.rate(Duration.minutes(1/2)); + }).toThrow(/must be a whole number of/); + }); + + test('rate cannot be less than 1 minute (defined with minutes as decimals)', () => { + expect(() => { + ScheduleExpression.rate(Duration.minutes(0.25)); + }).toThrow(/must be a whole number of/); + }); + + test('rate can be in minutes', () => { + expect('rate(10 minutes)').toEqual( + ScheduleExpression.rate(Duration.minutes(10)) + .expressionString); + }); +}); \ No newline at end of file From ec409854a8ba4b4043b7684c742f7379f13e488e Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Thu, 4 May 2023 22:54:16 +0000 Subject: [PATCH 02/21] Update README.md for scheduler module --- packages/aws-cdk-lib/aws-scheduler/README.md | 67 +++++++++++++++----- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/packages/aws-cdk-lib/aws-scheduler/README.md b/packages/aws-cdk-lib/aws-scheduler/README.md index 4f92747c20122..cae172fc6b86c 100644 --- a/packages/aws-cdk-lib/aws-scheduler/README.md +++ b/packages/aws-cdk-lib/aws-scheduler/README.md @@ -1,27 +1,64 @@ -# AWS::Scheduler Construct Library +# Amazon Scheduler Construct Library +Amazon EventBridge Scheduler](https://aws.amazon.com/blogs/compute/introducing-amazon-eventbridge-scheduler/) is a feature from Amazon EventBridge that allows you to create, run, and manage scheduled tasks at scale. With EventBridge Scheduler, you can schedule one-time or recurrently tens of millions of tasks across many AWS services without provisioning or managing underlying infrastructure. -This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. +1. **Schedule**: A schedule is the main resource you create, configure, and manage using Amazon EventBridge Scheduler. Every schedule has a schedule expression that determines when, and with what frequency, the schedule runs. EventBridge Scheduler supports three types of schedules: rate, cron, and one-time schedules. When you create a schedule, you configure a target for the schedule to invoke. +2. **Targets**: A target is an API operation that EventBridge Scheduler calls on your behalf every time your schedule runs. EventBridge Scheduler supports two types of targets: templated targets and universal targets. Templated targets invoke common API operations across a core groups of services. For example, EventBridge Scheduler supports templated targets for invoking AWS Lambda Function or starting execution of Step Function state machine. For API operations that are not supported by templated targets you can use customizeable universal targets. Universal targets support calling more than 6,000 API operations across over 270 AWS services. +3. **Schedule Group**: A schedule group is an Amazon EventBridge Scheduler resource that you use to organize your schedules. Your AWS account comes with a default scheduler group. A new schedule will always be added to a scheduling group. If you do not provide a scheduling group to add to, it will be added to the default scheduling group. You can create up to 500 schedule groups in your AWS account. Groups can be used to organize the schedules logically, access the schedule metrics and manage permissions at group granularity (see details below). Scheduling groups support tagging: with EventBridge Scheduler, you apply tags to schedule groups, not to individual schedules to organize your resources. -```ts nofixture -import * as scheduler from 'aws-cdk-lib/aws-scheduler'; -``` +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. - +## Defining a schedule -There are no official hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. Here are some suggestions on how to proceed: +```ts +const target = new targets.LambdaInvoke(props.func, { + input: ScheduleTargetInput.fromObject({ + "payload": "useful" + }) +}); + +const schedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), + target, + description: 'This is a test schedule that invokes lambda function every 10 minutes.', +}); +``` -- Search [Construct Hub for Scheduler construct libraries](https://constructs.dev/search?q=scheduler) -- Use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, in the same way you would use [the CloudFormation AWS::Scheduler resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Scheduler.html) directly. +### Schedule Expressions +You can choose from three schedule types when configuring your schedule: rate-based, cron-based, and one-time schedules. - +Both rate-based and cron-based schedules are recurring schedules. You can configure each recurring schedule type using a schedule expression. For cron-based schedule you can specify a time zone in which EventBridge Scheduler evaluates the expression. -There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. -However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. +```ts +const rateBasedSchedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), + target, + description: 'This is a test rate-based schedule', +}); -For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::Scheduler](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Scheduler.html). +const cronBasedSchedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.cron({ + minute: '0', + hour: '23', + day: '20', + month: '11', + timeZone: TimeZone.AMERICA_NEW_YORK + }), + target, + description: 'This is a test cron-based schedule that will run at 11:00 PM, on day 20 of the month, only in November in New York timezone', +}); +``` -(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and submit an RFC if you are interested in contributing to this construct library.) +A one-time schedule is a schedule that invokes a target only once. You configure a one-time schedule when by specifying the time of the day, date, and time zone in which EventBridge Scheduler evaluates the schedule. - +```ts +const oneTimeSchedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.at( + new Date(2022, 10, 20, 19, 20, 23) + TimeZone.AMERICA_NEW_YORK + ) + target, + description: 'This is a one-time schedule in New York timezone', +}); +``` \ No newline at end of file From 7f9b377a35ba7075c6ddbf443ad40ec87ba9cd40 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> Date: Fri, 5 May 2023 15:59:55 -0400 Subject: [PATCH 03/21] Apply suggestions from code review --- packages/aws-cdk-lib/aws-scheduler/README.md | 12 ++++++------ packages/aws-cdk-lib/aws-scheduler/lib/index.ts | 1 + .../aws-scheduler/lib/schedule-expression.ts | 2 -- .../aws-scheduler/test/schedule-expression.test.ts | 1 - 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/aws-cdk-lib/aws-scheduler/README.md b/packages/aws-cdk-lib/aws-scheduler/README.md index cae172fc6b86c..188ea24df68f3 100644 --- a/packages/aws-cdk-lib/aws-scheduler/README.md +++ b/packages/aws-cdk-lib/aws-scheduler/README.md @@ -13,8 +13,8 @@ This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aw ```ts const target = new targets.LambdaInvoke(props.func, { input: ScheduleTargetInput.fromObject({ - "payload": "useful" - }) + payload: 'useful', + }), }); const schedule = new Schedule(this, 'Schedule', { @@ -43,7 +43,7 @@ const cronBasedSchedule = new Schedule(this, 'Schedule', { hour: '23', day: '20', month: '11', - timeZone: TimeZone.AMERICA_NEW_YORK + timeZone: TimeZone.AMERICA_NEW_YORK, }), target, description: 'This is a test cron-based schedule that will run at 11:00 PM, on day 20 of the month, only in November in New York timezone', @@ -55,9 +55,9 @@ A one-time schedule is a schedule that invokes a target only once. You configure ```ts const oneTimeSchedule = new Schedule(this, 'Schedule', { scheduleExpression: ScheduleExpression.at( - new Date(2022, 10, 20, 19, 20, 23) - TimeZone.AMERICA_NEW_YORK - ) + new Date(2022, 10, 20, 19, 20, 23), + TimeZone.AMERICA_NEW_YORK, + ), target, description: 'This is a one-time schedule in New York timezone', }); diff --git a/packages/aws-cdk-lib/aws-scheduler/lib/index.ts b/packages/aws-cdk-lib/aws-scheduler/lib/index.ts index 54b160ae64354..165bae689f5b8 100644 --- a/packages/aws-cdk-lib/aws-scheduler/lib/index.ts +++ b/packages/aws-cdk-lib/aws-scheduler/lib/index.ts @@ -1,2 +1,3 @@ export * from './scheduler.generated'; + export * from './schedule-expression'; \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts b/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts index 6548bac866507..2771df711e85b 100644 --- a/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts +++ b/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts @@ -13,8 +13,6 @@ import { Duration, TimeZone } from '../../core'; * @see https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html */ export abstract class ScheduleExpression { - - /** * Construct a one-time schedule from a date. * diff --git a/packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts b/packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts index 04c41a2e6c122..8a5934f2e8a3b 100644 --- a/packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts +++ b/packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts @@ -1,7 +1,6 @@ import { Duration, Stack, Lazy, TimeZone } from '../../core'; import { ScheduleExpression } from '../lib'; - describe('schedule expression', () => { test('cron expressions day and dow are mutex: given weekday', () => { // Run every 10 minutes Monday through Friday From 540a1abe2c78fcb099b52d23ebdd063a28061bb7 Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Sat, 6 May 2023 09:25:32 +0100 Subject: [PATCH 04/21] Update packages/aws-cdk-lib/aws-scheduler/README.md Co-authored-by: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> --- packages/aws-cdk-lib/aws-scheduler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-cdk-lib/aws-scheduler/README.md b/packages/aws-cdk-lib/aws-scheduler/README.md index 188ea24df68f3..fbdcb9e477c90 100644 --- a/packages/aws-cdk-lib/aws-scheduler/README.md +++ b/packages/aws-cdk-lib/aws-scheduler/README.md @@ -1,4 +1,4 @@ -# Amazon Scheduler Construct Library +# Amazon EventBridge Scheduler Construct Library Amazon EventBridge Scheduler](https://aws.amazon.com/blogs/compute/introducing-amazon-eventbridge-scheduler/) is a feature from Amazon EventBridge that allows you to create, run, and manage scheduled tasks at scale. With EventBridge Scheduler, you can schedule one-time or recurrently tens of millions of tasks across many AWS services without provisioning or managing underlying infrastructure. From 337b87719db08f0c82cdd772c47eaa20f52699d7 Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Sat, 6 May 2023 09:26:56 +0100 Subject: [PATCH 05/21] Update packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts Co-authored-by: Jacco Kulman --- .../aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts b/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts index 2771df711e85b..60492f79eabcb 100644 --- a/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts +++ b/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts @@ -69,9 +69,9 @@ export abstract class ScheduleExpression { protected constructor() {}; /** - * - * @internal - */ + * + * @internal + */ abstract _bind(scope: Construct): void; } From 1d56d3b2209b42a308b1b5848e383cbaa6d22fa6 Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Sat, 6 May 2023 09:28:21 +0100 Subject: [PATCH 06/21] Update packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts Co-authored-by: Jacco Kulman --- .../aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts b/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts index 60492f79eabcb..c6b9cfd117a53 100644 --- a/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts +++ b/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts @@ -54,8 +54,9 @@ export abstract class ScheduleExpression { * Create a srecurring chedule from a set of cron fields and time zone. */ static cron(options: CronOptionsWithTimezone): ScheduleExpression { - const schedule = events.Schedule.cron(options); - return new LiteralScheduleExpression(schedule.expressionString, options.timeZone ?? TimeZone.ETC_UTC); + const { timeZone, ...cronOptions } = options; + const schedule = events.Schedule.cron(cronOptions); + return new LiteralScheduleExpression(schedule.expressionString, timeZone ?? TimeZone.ETC_UTC); } /** From e07a4d21117ce65bc4e79594bdad64601844a4dc Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Sat, 6 May 2023 16:07:28 +0000 Subject: [PATCH 07/21] Move new L2 constructs to @aws-cdk/scheduler-alpha Move L2 constructs to @aws-cdk. Also add an experimental banner. --- .../@aws-cdk/aws-scheduler-alpha/.eslintrc.js | 8 + .../@aws-cdk/aws-scheduler-alpha/.gitignore | 24 ++ .../@aws-cdk/aws-scheduler-alpha/.npmignore | 39 ++ packages/@aws-cdk/aws-scheduler-alpha/LICENSE | 201 ++++++++++ packages/@aws-cdk/aws-scheduler-alpha/NOTICE | 2 + .../@aws-cdk/aws-scheduler-alpha/README.md | 348 ++++++++++++++++++ .../aws-scheduler-alpha/jest.config.js | 10 + .../@aws-cdk/aws-scheduler-alpha/lib/index.ts | 1 + .../lib/schedule-expression.ts | 22 +- .../@aws-cdk/aws-scheduler-alpha/package.json | 119 ++++++ .../test/schedule-expression.test.ts | 2 +- .../aws-scheduler-alpha/tsconfig.dev.json | 38 ++ .../aws-cdk-lib/aws-scheduler/lib/index.ts | 2 - 13 files changed, 798 insertions(+), 18 deletions(-) create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/.eslintrc.js create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/.gitignore create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/.npmignore create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/LICENSE create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/NOTICE create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/README.md create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/jest.config.js create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/lib/index.ts rename packages/{aws-cdk-lib/aws-scheduler => @aws-cdk/aws-scheduler-alpha}/lib/schedule-expression.ts (87%) create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/package.json rename packages/{aws-cdk-lib/aws-scheduler => @aws-cdk/aws-scheduler-alpha}/test/schedule-expression.test.ts (98%) create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/tsconfig.dev.json diff --git a/packages/@aws-cdk/aws-scheduler-alpha/.eslintrc.js b/packages/@aws-cdk/aws-scheduler-alpha/.eslintrc.js new file mode 100644 index 0000000000000..b284f20df26e9 --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/.eslintrc.js @@ -0,0 +1,8 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; + +baseConfig.rules['import/no-extraneous-dependencies'] = ['error', { devDependencies: true, peerDependencies: true } ]; +baseConfig.rules['import/order'] = 'off'; +baseConfig.rules['@aws-cdk/invalid-cfn-imports'] = 'off'; + +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-scheduler-alpha/.gitignore b/packages/@aws-cdk/aws-scheduler-alpha/.gitignore new file mode 100644 index 0000000000000..4b4c1e6d4716a --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/.gitignore @@ -0,0 +1,24 @@ +*.d.ts +*.generated.ts +*.js +*.js.map +*.snk +.jsii +.jsii.gz +.LAST_BUILD +.LAST_PACKAGE +nyc.config.js +.nyc_output +.vscode +.types-compat +coverage +dist +tsconfig.json +!.eslintrc.js +!jest.config.js + +junit.xml +!**/*.snapshot/**/asset.*/*.js +!**/*.snapshot/**/asset.*/*.d.ts + +!**/*.snapshot/**/asset.*/** diff --git a/packages/@aws-cdk/aws-scheduler-alpha/.npmignore b/packages/@aws-cdk/aws-scheduler-alpha/.npmignore new file mode 100644 index 0000000000000..39a19f1bc4c14 --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/.npmignore @@ -0,0 +1,39 @@ +# The basics +*.ts +*.tgz +*.snk +!*.d.ts +!*.js +test/ +**/test/** + +# Coverage +coverage +.nyc_output +.nycrc + +# Build gear +build-tools +dist +scripts +.LAST_BUILD +.LAST_PACKAGE + +tsconfig.json +*.tsbuildinfo + +!.jsii +!.jsii.gz +.eslintrc.js + +# exclude cdk artifacts +**/cdk.out +junit.xml + +!*.lit.ts + +# exclude source maps as they only work locally +*.map + +# Nested node_modules +aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/node_modules diff --git a/packages/@aws-cdk/aws-scheduler-alpha/LICENSE b/packages/@aws-cdk/aws-scheduler-alpha/LICENSE new file mode 100644 index 0000000000000..9b722c65c5481 --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-scheduler-alpha/NOTICE b/packages/@aws-cdk/aws-scheduler-alpha/NOTICE new file mode 100644 index 0000000000000..a27b7dd317649 --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-scheduler-alpha/README.md b/packages/@aws-cdk/aws-scheduler-alpha/README.md new file mode 100644 index 0000000000000..16f59ba6dd8b3 --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/README.md @@ -0,0 +1,348 @@ +# Amazon EventBridge Scheduler Construct Library + + +--- + +![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) + +> The APIs of higher level constructs in this module are experimental and under active development. +> They are subject to non-backward compatible changes or removal in any future version. These are +> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be +> announced in the release notes. This means that while you may use them, you may need to update +> your source code when upgrading to a newer version of this package. + +--- + + + +[Amazon EventBridge Scheduler](https://aws.amazon.com/blogs/compute/introducing-amazon-eventbridge-scheduler/) is a feature from Amazon EventBridge that allows you to create, run, and manage scheduled tasks at scale. With EventBridge Scheduler, you can schedule one-time or recurrently tens of millions of tasks across many AWS services without provisioning or managing underlying infrastructure. + +1. **Schedule**: A schedule is the main resource you create, configure, and manage using Amazon EventBridge Scheduler. Every schedule has a schedule expression that determines when, and with what frequency, the schedule runs. EventBridge Scheduler supports three types of schedules: rate, cron, and one-time schedules. When you create a schedule, you configure a target for the schedule to invoke. +2. **Targets**: A target is an API operation that EventBridge Scheduler calls on your behalf every time your schedule runs. EventBridge Scheduler supports two types of targets: templated targets and universal targets. Templated targets invoke common API operations across a core groups of services. For example, EventBridge Scheduler supports templated targets for invoking AWS Lambda Function or starting execution of Step Function state machine. For API operations that are not supported by templated targets you can use customizeable universal targets. Universal targets support calling more than 6,000 API operations across over 270 AWS services. +3. **Schedule Group**: A schedule group is an Amazon EventBridge Scheduler resource that you use to organize your schedules. Your AWS account comes with a default scheduler group. A new schedule will always be added to a scheduling group. If you do not provide a scheduling group to add to, it will be added to the default scheduling group. You can create up to 500 schedule groups in your AWS account. Groups can be used to organize the schedules logically, access the schedule metrics and manage permissions at group granularity (see details below). Scheduling groups support tagging: with EventBridge Scheduler, you apply tags to schedule groups, not to individual schedules to organize your resources. + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. It allows you to define Event Bridge Schedules. + + +## Defining a schedule + +```ts +const target = new targets.LambdaInvoke(props.func, { + input: ScheduleTargetInput.fromObject({ + "payload": "useful" + }) +}); + +const schedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), + target, + description: 'This is a test schedule that invokes lambda function every 10 minutes.', +}); +``` + +### Schedule Expressions + +You can choose from three schedule types when configuring your schedule: rate-based, cron-based, and one-time schedules. + +Both rate-based and cron-based schedules are recurring schedules. You can configure each recurring schedule type using a schedule expression. For cron-based schedule you can specify a time zone in which EventBridge Scheduler evaluates the expression. + +```ts +const rateBasedSchedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), + target, + description: 'This is a test rate-based schedule', +}); + +const cronBasedSchedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.cron({ + minute: '0', + hour: '23', + day: '20', + month: '11', + timeZone: TimeZone.AMERICA_NEW_YORK + }), + target, + description: 'This is a test cron-based schedule that will run at 11:00 PM, on day 20 of the month, only in November in New York timezone', +}); +``` + +A one-time schedule is a schedule that invokes a target only once. You configure a one-time schedule when by specifying the time of the day, date, and time zone in which EventBridge Scheduler evaluates the schedule. + +```ts +const oneTimeSchedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.at( + new Date(2022, 10, 20, 19, 20, 23) + TimeZone.AMERICA_NEW_YORK + ) + target, + description: 'This is a one-time schedule in New York timezone', +}); +``` + +### Grouping Schedules + +Your AWS account comes with a default scheduler group, which you can access in CDK with: + +```ts +const defaultGroup = Group.fromDefaultGroup(this, "DefaultGroup"); +``` + +When creating a new schedule, you can also add the schedule to a custom scheduling group managed by you: + +```ts +const group = new Group(this, "Group", { + groupName: "MyGroup" +}); + +const target = new targets.LambdaInvoke(props.func, { + input: ScheduleTargetInput.fromObject({ + "payload": "useful" + }) +}); + +const schedule1 = new Schedule(this, 'Schedule1', { + scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), + target +}); + +const schedule2 = new Schedule(this, 'Schedule2', { + scheduleExpression: ScheduleExpression.rate(Duration.minutes(5)), + target +}); + +group.addSchedules(schedule1, schedule2); + +// You can also assign groups in a schedule constructor: +const schedule3 = new Schedule(this, 'Schedule2', { + scheduleExpression: ScheduleExpression.rate(Duration.minutes(5)), + group, + target +}); +``` + +## Scheduler Targets + +The `@aws-cdk/aws-schedule-targets` module includes classes that implement the `IScheduleTarget` interface for various AWS services. EventBridge Scheduler supports two types of targets: templated targets invoke common API operations across a core groups of services, and customizeable universal targets that you can use to call more than 6,000 operations across over 270 services. + +Templated targets are a set of common API operations across a group of core AWS services such as Amazon SQS, Lambda, and Step Functions. The module contains CDK constructs for templated targets. For example, you can use construct `targets.LambdaInvoke` to target Lambda's Invoke API operation by providing a `lambda.IFunction`, or use `targets.SqsSendMessage` with a `sqs.IQueue` to send a message to SQS queue. + + +The following templated targets are supported: + +1. `targets.CodeBuildStartBuild`: Start an AWS CodeBuild build +1. `targets.CodePipelineStartPipelineExecution`: Start an AWS CodePipeline pipeline execution +1. `targets.StepFunctionsStartExecution`: Trigger an AWS Step Functions state machine +1. `targets.KinesisDataFirehosePutRecord`: Put a record to a Kinesis Firehose +1. `targets.KinesisStreamPutRecord`: Put a record to a Kinesis Stream +1. `targets.InspectorStartAssessmentRun`: Start an AWS Inspector assessment run +1. `targets.EventBridgePutEvents`: Put an event to an AWS Event Bridge Event Bus +1. `targets.EcsTask`: Start a task on an Amazon ECS cluster +1. `targets.SageMakerStartPipelineExecution`: Start Amazon SageMaker pipeline +1. `targets.LambdaInvoke`: Invoke an AWS Lambda function +1. `targets.SqsSendMessage`: Send a message to an Amazon SQS Queue +1. `targets.SnsPublish`: Publish a message into an SNS topic + + +A universal target is a customizable set of parameters that allow you to invoke a wider set of API operation for many AWS services. To create a universal target you need to specify `input`, service name and service action. See [full list of support universal targets](https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html#supported-universal-targets). + +For example, to create a schedule that will create a SQS queue every hour: + +```ts +const input = ScheduleTargetInput.fromObject({ + 'QueueName': 'MyQueue' +}); + +const schedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.rate(Duration.hours(1)), + target: new targets.Universal('sqs', 'CreateQueue', { input: input }) +}); +``` + +### Input + +Target can be invoked with a custom input. Class `ScheduleTargetInput` supports free form text input and JSON-formatted object input: + +```ts +const input = ScheduleTargetInput.fromObject({ + 'QueueName': 'MyQueue' +}); +``` + +You can include context attributes in your target payload. EventBridge Scheduler will replace each keyword with its respective value and deliver it to the target. See [full list of supported context attributes](https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-schedule-context-attributes.html): + +1. `ContextAttribute.scheduleArn()` – The ARN of the schedule. +2. `ContextAttribute.scheduledTime()` – The time you specified for the schedule to invoke its target, for example, 2022-03-22T18:59:43Z. +3. `ContextAttribute.executionId()` – The unique ID that EventBridge Scheduler assigns for each attempted invocation of a target, for example, d32c5kddcf5bb8c3. +4. `ContextAttribute.attemptNumber()` – A counter that identifies the attempt number for the current invocation, for example, 1. + +```ts +const text = `Attempt number: ${ContextAttribute.attemptNumber}`; +const input = scheduler.ScheduleTargetInput.fromInput(text); +``` + + +### Specifying Execution Role + +An execution role is an IAM role that EventBridge Scheduler assumes in order to interact with other AWS services on your behalf. + +The classes for templated schedule targets automatically create an IAM role with all the minimum necessary +permissions to interact with the templated target. If you wish you may specify your own IAM role, then the templated targets +will grant minimal required permissions. For example: for invoking Lambda function target `LambdaInvoke` will grant +execution IAM role permission to `lambda:InvokeFunction`. + +```ts +import * as iam from '@aws-cdk/aws-iam'; + +declare const fn: lambda.Function; + +const role = new iam.Role(this, 'Role', { + assumedBy: new iam.ServicePrincipal('scheduler.amazonaws.com'), +}); + +const target = new targets.LambdaInvoke({ + input: ScheduleTargetInput.fromObject({ + "payload": "useful" + }), + role, +}, fn); +``` + +Universal target automatically create an IAM role if you do not specify your own IAM role. However, in comparison with templated targets, for universal targets you must grant the required IAM permissions yourself. + +```ts +const input = ScheduleTargetInput.fromObject({ + 'QueueName': 'MyQueue' +}); + +const target = new targets.Universal('sqs', 'CreateQueue', { input: input }); + +target.role.addToPolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + resources: '*', + actions: ['sqs:CreateQueue'] +})); + +const schedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.rate(Duration.hours(1)), + target +}); +``` + +### Cross-account and cross-region targets + +Executing cross-account and cross-region targets are not supported yet. + +### Specifying Encryption key + +EventBridge Scheduler integrates with AWS Key Management Service (AWS KMS) to encrypt and decrypt your data using an AWS KMS key. EventBridge Scheduler supports two types of KMS keys: AWS owned keys, and customer managed keys. + +By default, all events in Scheduler are encrypted with a key that AWS owns and manages. +If you wish you can also provide a customer managed key to encrypt and decrypt the payload that your schedule delivers +to its target. Target classes will automatically add AWS KMS Decrypt permission to your schedule's execution role +permissions policy + +```ts +import * as kms from '@aws-cdk/aws-kms'; + +const key = new kms.Key(this, 'Key'); + +const schedule = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), + target, + key: key, +}); +``` + +See: [Data Protection](https://docs.aws.amazon.com/scheduler/latest/UserGuide/data-protection.html) in +the *Amazon EventBridge Scheduler User Guide*. + +## Error-handling + +You can configure how your schedule handles failures, when EventBridge Scheduler is unable to deliver an event +successfully to a target, by using two primary mechanisms: a retry policy, and a dead-letter queue (DLQ). + +A retry policy determines the number of times EventBridge Scheduler must retry a failed event, and how long +to keep an unprocessed event. + +A DLQ is a standard Amazon SQS queue EventBridge Scheduler uses to deliver failed events to, after the retry +policy has been exhausted. You can use a DLQ to troubleshoot issues with your schedule or its downstream target. +If you've configured a retry policy for your schedule, EventBridge Scheduler delivers the dead-letter event after +exhausting the maximum number of retries you set in the retry policy. + +```ts +const dlq = new Queue(this, "DLQ", { + queueName: 'MyDLQ', +}); + +const target = new targets.LambdaInvoke(props.func, { + deadLetterQueue: dlq, + maximumEventAge: Duration.minutes(1), + maximumRetryAttempts: 3 +}); +``` + +## Overriding Target Properties + +If you wish to reuse the same target in multiple schedules, you can override target properties +like `input`, `maximumRetryAttempts` and `maximumEventAge` when creating a Schedule: + +```ts +const target = new targets.LambdaInvoke(props.func, { + input: ScheduleTargetInput.fromObject({ + "payload": "useful" + }), +}); + +const schedule1 = new Schedule(this, 'Schedule', { + scheduleExpression: ScheduleExpression.cron({ day: '20' }), + target, +}); + +const schedule2 = new Schedule(this, 'Schedule2', { + scheduleExpression: ScheduleExpression.cron({ day: '5' }) + target, + targetOverrides: { + input: ScheduleTargetInput.fromText("Overriding Target Input") + } +}); +``` + +## Monitoring + +You can monitor Amazon EventBridge Scheduler using CloudWatch, which collects raw data +and processes it into readable, near real-time metrics. EventBridge Scheduler emits +a set of metrics for all schedules, and an additional set of metrics for schedules that +have an associated dead-letter queue (DLQ). If you configure a DLQ for your schedule, +EventBridge Scheduler publishes additional metrics when your schedule exhausts its retry policy. + +### Metrics for all schedules + +Class `Schedule` provides static methods for accessing all schedules metrics with default configuration, +such as `metricAllErrors` for viewing errors when executing targets. + +```ts + +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; + +new Alarm(this, 'SchedulesErrorAlarm', { + metric: Schedule.metricAllErrors(), + threshold: 0 +}); +``` + +### Metrics for a Group + +To view metrics for a specific group you can use methods on class `Group`: + +```ts +const group = new Group(this, "Group", { + groupName: "MyGroup" +}); + +new Alarm(this, 'MyGroupErrorAlarm', { + metric: group.metricAllErrors(), + threshold: 0 +}); +``` + +See full list of metrics and their description at [Monitoring Using CloudWatch Metrics](https://docs.aws.amazon.com/scheduler/latest/UserGuide/monitoring-cloudwatch.html) in the *AWS Event Bridge Scheduler User Guide*. diff --git a/packages/@aws-cdk/aws-scheduler-alpha/jest.config.js b/packages/@aws-cdk/aws-scheduler-alpha/jest.config.js new file mode 100644 index 0000000000000..7ea6abe8036b2 --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/jest.config.js @@ -0,0 +1,10 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = { + ...baseConfig, + coverageThreshold: { + global: { + ...baseConfig.coverageThreshold.global, + branches: 60, + }, + }, + };; diff --git a/packages/@aws-cdk/aws-scheduler-alpha/lib/index.ts b/packages/@aws-cdk/aws-scheduler-alpha/lib/index.ts new file mode 100644 index 0000000000000..c00ab258ae963 --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/lib/index.ts @@ -0,0 +1 @@ +export * from './schedule-expression'; \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts similarity index 87% rename from packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts rename to packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts index c6b9cfd117a53..cbfedbe4dd5fc 100644 --- a/packages/aws-cdk-lib/aws-scheduler/lib/schedule-expression.ts +++ b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts @@ -1,7 +1,5 @@ -import { Construct } from 'constructs'; -import * as events from '../../aws-events'; -import { CronOptions } from '../../aws-events'; -import { Duration, TimeZone } from '../../core'; +import { Duration, TimeZone } from 'aws-cdk-lib'; +import * as events from 'aws-cdk-lib/aws-events'; /** @@ -56,7 +54,7 @@ export abstract class ScheduleExpression { static cron(options: CronOptionsWithTimezone): ScheduleExpression { const { timeZone, ...cronOptions } = options; const schedule = events.Schedule.cron(cronOptions); - return new LiteralScheduleExpression(schedule.expressionString, timeZone ?? TimeZone.ETC_UTC); + return new LiteralScheduleExpression(schedule.expressionString, timeZone); } /** @@ -69,11 +67,6 @@ export abstract class ScheduleExpression { public abstract readonly timeZone?: TimeZone; protected constructor() {}; - /** - * - * @internal - */ - abstract _bind(scope: Construct): void; } /** @@ -84,7 +77,7 @@ export abstract class ScheduleExpression { * * @see https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html#cron-expressions */ -export interface CronOptionsWithTimezone extends CronOptions { +export interface CronOptionsWithTimezone extends events.CronOptions { /** * The timezone to run the schedule in * @@ -93,11 +86,10 @@ export interface CronOptionsWithTimezone extends CronOptions { readonly timeZone?: TimeZone; } -class LiteralScheduleExpression extends ScheduleExpression { +const DEFAULT_TIMEZONE = TimeZone.ETC_UTC; - constructor(public readonly expressionString: string, public readonly timeZone?: TimeZone) { +class LiteralScheduleExpression extends ScheduleExpression { + constructor(public readonly expressionString: string, public readonly timeZone: TimeZone = DEFAULT_TIMEZONE) { super(); } - - public _bind() {} } diff --git a/packages/@aws-cdk/aws-scheduler-alpha/package.json b/packages/@aws-cdk/aws-scheduler-alpha/package.json new file mode 100644 index 0000000000000..e1570d8e6e176 --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/package.json @@ -0,0 +1,119 @@ +{ + "name": "aws-scheduler-alpha", + "version": "0.0.0", + "description": "The CDK Construct Library for Amazon Scheduler", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "targets": { + "java": { + "package": "software.amazon.awscdk.services.scheduler.alpha", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "scheduler-alpha" + } + }, + "dotnet": { + "namespace": "Amazon.CDK.AWS.Scheduler.Alpha", + "packageId": "Amazon.CDK.AWS.Scheduler.Alpha", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/main/logo/default-256-dark.png" + }, + "python": { + "distName": "aws-cdk.aws-scheduler-alpha", + "module": "aws_cdk.aws_scheduler_alpha", + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 2" + ] + }, + "go": { + "moduleName": "github.com/aws/aws-cdk-go", + "packageName": "awscdkscheduleralpha" + } + }, + "projectReferences": true, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-scheduler-alpha" + }, + "homepage": "https://github.com/aws/aws-cdk", + "scripts": { + "build": "cdk-build", + "integ": "integ-runner", + "lint": "cdk-lint", + "package": "cdk-package", + "awslint": "cdk-awslint", + "pkglint": "pkglint -f", + "test": "cdk-test", + "watch": "cdk-watch", + "compat": "cdk-compat", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "env": { + "AWSLINT_BASE_CONSTRUCT": true + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "aws-scheduler" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/cfn2ts": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^29.5.0", + "aws-cdk-lib": "0.0.0", + "constructs": "^10.0.0" + }, + "dependencies": {}, + "peerDependencies": { + "aws-cdk-lib": "^0.0.0", + "constructs": "^10.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "stability": "experimental", + "maturity": "experimental", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + }, + "awslint": { + "exclude": [ + "*:*" + ] + }, + "pkglint": { + "exclude": [ + "naming/package-matches-directory", + "assert/assert-dependency" + ] + } +} diff --git a/packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts b/packages/@aws-cdk/aws-scheduler-alpha/test/schedule-expression.test.ts similarity index 98% rename from packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts rename to packages/@aws-cdk/aws-scheduler-alpha/test/schedule-expression.test.ts index 8a5934f2e8a3b..06fdb794ca600 100644 --- a/packages/aws-cdk-lib/aws-scheduler/test/schedule-expression.test.ts +++ b/packages/@aws-cdk/aws-scheduler-alpha/test/schedule-expression.test.ts @@ -1,4 +1,4 @@ -import { Duration, Stack, Lazy, TimeZone } from '../../core'; +import { Duration, Lazy, Stack, TimeZone } from 'aws-cdk-lib'; import { ScheduleExpression } from '../lib'; describe('schedule expression', () => { diff --git a/packages/@aws-cdk/aws-scheduler-alpha/tsconfig.dev.json b/packages/@aws-cdk/aws-scheduler-alpha/tsconfig.dev.json new file mode 100644 index 0000000000000..4470bb29bf6da --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/tsconfig.dev.json @@ -0,0 +1,38 @@ +{ + "$": "Config file for ts-node", + "ts-node": { + "preferTsExts": true + }, + "compilerOptions": { + "alwaysStrict": true, + "experimentalDecorators": true, + "incremental": true, + "lib": [ + "es2020" + ], + "module": "CommonJS", + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": false, + "target": "ES2020", + "composite": false, + "tsBuildInfoFile": "tsconfig.dev.tsbuildinfo" + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "node_modules", + ".types-compat", + "**/*.d.ts" + ] +} diff --git a/packages/aws-cdk-lib/aws-scheduler/lib/index.ts b/packages/aws-cdk-lib/aws-scheduler/lib/index.ts index 165bae689f5b8..7efa6ad19129c 100644 --- a/packages/aws-cdk-lib/aws-scheduler/lib/index.ts +++ b/packages/aws-cdk-lib/aws-scheduler/lib/index.ts @@ -1,3 +1 @@ export * from './scheduler.generated'; - -export * from './schedule-expression'; \ No newline at end of file From 4c6abd7496b6171a5bcb1bf7b12d287497fd557f Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Sat, 6 May 2023 16:22:22 +0000 Subject: [PATCH 08/21] Revert changes to files in aws-cdk-lib --- packages/aws-cdk-lib/aws-scheduler/README.md | 67 +++++-------------- .../aws-cdk-lib/aws-scheduler/lib/index.ts | 2 +- 2 files changed, 16 insertions(+), 53 deletions(-) diff --git a/packages/aws-cdk-lib/aws-scheduler/README.md b/packages/aws-cdk-lib/aws-scheduler/README.md index fbdcb9e477c90..4f92747c20122 100644 --- a/packages/aws-cdk-lib/aws-scheduler/README.md +++ b/packages/aws-cdk-lib/aws-scheduler/README.md @@ -1,64 +1,27 @@ -# Amazon EventBridge Scheduler Construct Library +# AWS::Scheduler Construct Library -Amazon EventBridge Scheduler](https://aws.amazon.com/blogs/compute/introducing-amazon-eventbridge-scheduler/) is a feature from Amazon EventBridge that allows you to create, run, and manage scheduled tasks at scale. With EventBridge Scheduler, you can schedule one-time or recurrently tens of millions of tasks across many AWS services without provisioning or managing underlying infrastructure. - -1. **Schedule**: A schedule is the main resource you create, configure, and manage using Amazon EventBridge Scheduler. Every schedule has a schedule expression that determines when, and with what frequency, the schedule runs. EventBridge Scheduler supports three types of schedules: rate, cron, and one-time schedules. When you create a schedule, you configure a target for the schedule to invoke. -2. **Targets**: A target is an API operation that EventBridge Scheduler calls on your behalf every time your schedule runs. EventBridge Scheduler supports two types of targets: templated targets and universal targets. Templated targets invoke common API operations across a core groups of services. For example, EventBridge Scheduler supports templated targets for invoking AWS Lambda Function or starting execution of Step Function state machine. For API operations that are not supported by templated targets you can use customizeable universal targets. Universal targets support calling more than 6,000 API operations across over 270 AWS services. -3. **Schedule Group**: A schedule group is an Amazon EventBridge Scheduler resource that you use to organize your schedules. Your AWS account comes with a default scheduler group. A new schedule will always be added to a scheduling group. If you do not provide a scheduling group to add to, it will be added to the default scheduling group. You can create up to 500 schedule groups in your AWS account. Groups can be used to organize the schedules logically, access the schedule metrics and manage permissions at group granularity (see details below). Scheduling groups support tagging: with EventBridge Scheduler, you apply tags to schedule groups, not to individual schedules to organize your resources. This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. -## Defining a schedule - -```ts -const target = new targets.LambdaInvoke(props.func, { - input: ScheduleTargetInput.fromObject({ - payload: 'useful', - }), -}); - -const schedule = new Schedule(this, 'Schedule', { - scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), - target, - description: 'This is a test schedule that invokes lambda function every 10 minutes.', -}); +```ts nofixture +import * as scheduler from 'aws-cdk-lib/aws-scheduler'; ``` -### Schedule Expressions + -You can choose from three schedule types when configuring your schedule: rate-based, cron-based, and one-time schedules. +There are no official hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. Here are some suggestions on how to proceed: -Both rate-based and cron-based schedules are recurring schedules. You can configure each recurring schedule type using a schedule expression. For cron-based schedule you can specify a time zone in which EventBridge Scheduler evaluates the expression. +- Search [Construct Hub for Scheduler construct libraries](https://constructs.dev/search?q=scheduler) +- Use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, in the same way you would use [the CloudFormation AWS::Scheduler resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Scheduler.html) directly. -```ts -const rateBasedSchedule = new Schedule(this, 'Schedule', { - scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), - target, - description: 'This is a test rate-based schedule', -}); -const cronBasedSchedule = new Schedule(this, 'Schedule', { - scheduleExpression: ScheduleExpression.cron({ - minute: '0', - hour: '23', - day: '20', - month: '11', - timeZone: TimeZone.AMERICA_NEW_YORK, - }), - target, - description: 'This is a test cron-based schedule that will run at 11:00 PM, on day 20 of the month, only in November in New York timezone', -}); -``` + + +There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. +However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. + +For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::Scheduler](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Scheduler.html). -A one-time schedule is a schedule that invokes a target only once. You configure a one-time schedule when by specifying the time of the day, date, and time zone in which EventBridge Scheduler evaluates the schedule. +(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and submit an RFC if you are interested in contributing to this construct library.) -```ts -const oneTimeSchedule = new Schedule(this, 'Schedule', { - scheduleExpression: ScheduleExpression.at( - new Date(2022, 10, 20, 19, 20, 23), - TimeZone.AMERICA_NEW_YORK, - ), - target, - description: 'This is a one-time schedule in New York timezone', -}); -``` \ No newline at end of file + diff --git a/packages/aws-cdk-lib/aws-scheduler/lib/index.ts b/packages/aws-cdk-lib/aws-scheduler/lib/index.ts index 7efa6ad19129c..ae3df1e12b699 100644 --- a/packages/aws-cdk-lib/aws-scheduler/lib/index.ts +++ b/packages/aws-cdk-lib/aws-scheduler/lib/index.ts @@ -1 +1 @@ -export * from './scheduler.generated'; +export * from './scheduler.generated'; \ No newline at end of file From 98d227eaadac77ff418a26551916600fd83d8fbe Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Sat, 6 May 2023 17:29:30 +0100 Subject: [PATCH 09/21] Reformat readme.md file --- .../@aws-cdk/aws-scheduler-alpha/README.md | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/README.md b/packages/@aws-cdk/aws-scheduler-alpha/README.md index 16f59ba6dd8b3..e80fd2b75eee0 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/README.md +++ b/packages/@aws-cdk/aws-scheduler-alpha/README.md @@ -15,11 +15,21 @@ -[Amazon EventBridge Scheduler](https://aws.amazon.com/blogs/compute/introducing-amazon-eventbridge-scheduler/) is a feature from Amazon EventBridge that allows you to create, run, and manage scheduled tasks at scale. With EventBridge Scheduler, you can schedule one-time or recurrently tens of millions of tasks across many AWS services without provisioning or managing underlying infrastructure. +[Amazon EventBridge Scheduler](https://aws.amazon.com/blogs/compute/introducing-amazon-eventbridge-scheduler/) is a feature from Amazon EventBridge +that allows you to create, run, and manage scheduled tasks at scale. With EventBridge Scheduler, you can schedule one-time or recurrently tens +of millions of tasks across many AWS services without provisioning or managing underlying infrastructure. 1. **Schedule**: A schedule is the main resource you create, configure, and manage using Amazon EventBridge Scheduler. Every schedule has a schedule expression that determines when, and with what frequency, the schedule runs. EventBridge Scheduler supports three types of schedules: rate, cron, and one-time schedules. When you create a schedule, you configure a target for the schedule to invoke. -2. **Targets**: A target is an API operation that EventBridge Scheduler calls on your behalf every time your schedule runs. EventBridge Scheduler supports two types of targets: templated targets and universal targets. Templated targets invoke common API operations across a core groups of services. For example, EventBridge Scheduler supports templated targets for invoking AWS Lambda Function or starting execution of Step Function state machine. For API operations that are not supported by templated targets you can use customizeable universal targets. Universal targets support calling more than 6,000 API operations across over 270 AWS services. -3. **Schedule Group**: A schedule group is an Amazon EventBridge Scheduler resource that you use to organize your schedules. Your AWS account comes with a default scheduler group. A new schedule will always be added to a scheduling group. If you do not provide a scheduling group to add to, it will be added to the default scheduling group. You can create up to 500 schedule groups in your AWS account. Groups can be used to organize the schedules logically, access the schedule metrics and manage permissions at group granularity (see details below). Scheduling groups support tagging: with EventBridge Scheduler, you apply tags to schedule groups, not to individual schedules to organize your resources. +2. **Targets**: A target is an API operation that EventBridge Scheduler calls on your behalf every time your schedule runs. EventBridge Scheduler +supports two types of targets: templated targets and universal targets. Templated targets invoke common API operations across a core groups of +services. For example, EventBridge Scheduler supports templated targets for invoking AWS Lambda Function or starting execution of Step Function state +machine. For API operations that are not supported by templated targets you can use customizeable universal targets. Universal targets support calling +more than 6,000 API operations across over 270 AWS services. +3. **Schedule Group**: A schedule group is an Amazon EventBridge Scheduler resource that you use to organize your schedules. Your AWS account comes +with a default scheduler group. A new schedule will always be added to a scheduling group. If you do not provide a scheduling group to add to, it +will be added to the default scheduling group. You can create up to 500 schedule groups in your AWS account. Groups can be used to organize the +schedules logically, access the schedule metrics and manage permissions at group granularity (see details below). Scheduling groups support tagging: +with EventBridge Scheduler, you apply tags to schedule groups, not to individual schedules to organize your resources. This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. It allows you to define Event Bridge Schedules. @@ -44,7 +54,8 @@ const schedule = new Schedule(this, 'Schedule', { You can choose from three schedule types when configuring your schedule: rate-based, cron-based, and one-time schedules. -Both rate-based and cron-based schedules are recurring schedules. You can configure each recurring schedule type using a schedule expression. For cron-based schedule you can specify a time zone in which EventBridge Scheduler evaluates the expression. +Both rate-based and cron-based schedules are recurring schedules. You can configure each recurring schedule type using a schedule expression. For +cron-based schedule you can specify a time zone in which EventBridge Scheduler evaluates the expression. ```ts const rateBasedSchedule = new Schedule(this, 'Schedule', { @@ -66,7 +77,8 @@ const cronBasedSchedule = new Schedule(this, 'Schedule', { }); ``` -A one-time schedule is a schedule that invokes a target only once. You configure a one-time schedule when by specifying the time of the day, date, and time zone in which EventBridge Scheduler evaluates the schedule. +A one-time schedule is a schedule that invokes a target only once. You configure a one-time schedule when by specifying the time of the day, date, +and time zone in which EventBridge Scheduler evaluates the schedule. ```ts const oneTimeSchedule = new Schedule(this, 'Schedule', { @@ -122,9 +134,13 @@ const schedule3 = new Schedule(this, 'Schedule2', { ## Scheduler Targets -The `@aws-cdk/aws-schedule-targets` module includes classes that implement the `IScheduleTarget` interface for various AWS services. EventBridge Scheduler supports two types of targets: templated targets invoke common API operations across a core groups of services, and customizeable universal targets that you can use to call more than 6,000 operations across over 270 services. +The `@aws-cdk/aws-schedule-targets` module includes classes that implement the `IScheduleTarget` interface for various AWS services. +EventBridge Scheduler supports two types of targets: templated targets invoke common API operations across a core groups of services, +and customizeable universal targets that you can use to call more than 6,000 operations across over 270 services. -Templated targets are a set of common API operations across a group of core AWS services such as Amazon SQS, Lambda, and Step Functions. The module contains CDK constructs for templated targets. For example, you can use construct `targets.LambdaInvoke` to target Lambda's Invoke API operation by providing a `lambda.IFunction`, or use `targets.SqsSendMessage` with a `sqs.IQueue` to send a message to SQS queue. +Templated targets are a set of common API operations across a group of core AWS services such as Amazon SQS, Lambda, and Step Functions. +The module contains CDK constructs for templated targets. For example, you can use construct `targets.LambdaInvoke` to target Lambda's Invoke API +operation by providing a `lambda.IFunction`, or use `targets.SqsSendMessage` with a `sqs.IQueue` to send a message to SQS queue. The following templated targets are supported: @@ -143,7 +159,9 @@ The following templated targets are supported: 1. `targets.SnsPublish`: Publish a message into an SNS topic -A universal target is a customizable set of parameters that allow you to invoke a wider set of API operation for many AWS services. To create a universal target you need to specify `input`, service name and service action. See [full list of support universal targets](https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html#supported-universal-targets). +A universal target is a customizable set of parameters that allow you to invoke a wider set of API operation for many AWS services. +To create a universal target you need to specify `input`, service name and service action. See +[full list of support universal targets](https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html#supported-universal-targets). For example, to create a schedule that will create a SQS queue every hour: @@ -168,11 +186,12 @@ const input = ScheduleTargetInput.fromObject({ }); ``` -You can include context attributes in your target payload. EventBridge Scheduler will replace each keyword with its respective value and deliver it to the target. See [full list of supported context attributes](https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-schedule-context-attributes.html): +You can include context attributes in your target payload. EventBridge Scheduler will replace each keyword with its respective value and deliver it +to the target. See [full list of supported context attributes](https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-schedule-context-attributes.html): 1. `ContextAttribute.scheduleArn()` – The ARN of the schedule. 2. `ContextAttribute.scheduledTime()` – The time you specified for the schedule to invoke its target, for example, 2022-03-22T18:59:43Z. -3. `ContextAttribute.executionId()` – The unique ID that EventBridge Scheduler assigns for each attempted invocation of a target, for example, d32c5kddcf5bb8c3. +3. `ContextAttribute.executionId()` – The unique ID that EventBridge Scheduler assigns for each attempted invocation of a target, for example d32c5kddcf5bb8c3. 4. `ContextAttribute.attemptNumber()` – A counter that identifies the attempt number for the current invocation, for example, 1. ```ts @@ -207,7 +226,8 @@ const target = new targets.LambdaInvoke({ }, fn); ``` -Universal target automatically create an IAM role if you do not specify your own IAM role. However, in comparison with templated targets, for universal targets you must grant the required IAM permissions yourself. +Universal target automatically create an IAM role if you do not specify your own IAM role. However, in comparison with templated targets, +for universal targets you must grant the required IAM permissions yourself. ```ts const input = ScheduleTargetInput.fromObject({ @@ -234,7 +254,8 @@ Executing cross-account and cross-region targets are not supported yet. ### Specifying Encryption key -EventBridge Scheduler integrates with AWS Key Management Service (AWS KMS) to encrypt and decrypt your data using an AWS KMS key. EventBridge Scheduler supports two types of KMS keys: AWS owned keys, and customer managed keys. +EventBridge Scheduler integrates with AWS Key Management Service (AWS KMS) to encrypt and decrypt your data using an AWS KMS key. +EventBridge Scheduler supports two types of KMS keys: AWS owned keys, and customer managed keys. By default, all events in Scheduler are encrypted with a key that AWS owns and manages. If you wish you can also provide a customer managed key to encrypt and decrypt the payload that your schedule delivers From 34968a24762398faeac845601baed4cedfc0f7ae Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Sun, 14 May 2023 20:23:23 +0100 Subject: [PATCH 10/21] Update packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts Co-authored-by: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> --- .../@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts index cbfedbe4dd5fc..c51c77214bf61 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts +++ b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts @@ -43,7 +43,7 @@ export abstract class ScheduleExpression { * * Rates may be defined with any unit of time, but when converted into minutes, the duration must be a positive whole number of minutes. */ - static rate(duration: Duration): ScheduleExpression { + public static rate(duration: Duration): ScheduleExpression { const schedule = events.Schedule.rate(duration); return new LiteralScheduleExpression(schedule.expressionString); } From a6fabd58d6c5a46bf5eeda1c08d68bbc7d11e7c0 Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Sun, 14 May 2023 20:25:12 +0100 Subject: [PATCH 11/21] Update packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts Co-authored-by: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> --- .../@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts index c51c77214bf61..f8e86538a73d0 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts +++ b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts @@ -81,7 +81,7 @@ export interface CronOptionsWithTimezone extends events.CronOptions { /** * The timezone to run the schedule in * - * @default - UTC + * @default - TimeZone.ETC_UTC */ readonly timeZone?: TimeZone; } From 34cc3e78663b99616f5c19c519b1b8854e7a9f4b Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Sun, 14 May 2023 20:25:44 +0100 Subject: [PATCH 12/21] Update packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts Co-authored-by: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> --- .../@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts index f8e86538a73d0..b35786a88292c 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts +++ b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts @@ -51,7 +51,7 @@ export abstract class ScheduleExpression { /** * Create a srecurring chedule from a set of cron fields and time zone. */ - static cron(options: CronOptionsWithTimezone): ScheduleExpression { + public static cron(options: CronOptionsWithTimezone): ScheduleExpression { const { timeZone, ...cronOptions } = options; const schedule = events.Schedule.cron(cronOptions); return new LiteralScheduleExpression(schedule.expressionString, timeZone); From 10d388f52b604b1bc917eef41a1de300bfb4d238 Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Sun, 14 May 2023 20:25:57 +0100 Subject: [PATCH 13/21] Update packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts Co-authored-by: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> --- .../@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts index b35786a88292c..ae596d5b2ac2d 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts +++ b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts @@ -49,7 +49,7 @@ export abstract class ScheduleExpression { } /** - * Create a srecurring chedule from a set of cron fields and time zone. + * Create a recurring schedule from a set of cron fields and time zone. */ public static cron(options: CronOptionsWithTimezone): ScheduleExpression { const { timeZone, ...cronOptions } = options; From 5802931838d4e600d1462c9d62816126f84a8dd6 Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Mon, 15 May 2023 08:27:00 +0100 Subject: [PATCH 14/21] Rename package name to "@aws-cdk/aws-scheduler-alpha" --- packages/@aws-cdk/aws-scheduler-alpha/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/package.json b/packages/@aws-cdk/aws-scheduler-alpha/package.json index e1570d8e6e176..8d7f7956d3a0e 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/package.json +++ b/packages/@aws-cdk/aws-scheduler-alpha/package.json @@ -1,5 +1,5 @@ { - "name": "aws-scheduler-alpha", + "name": "@aws-cdk/aws-scheduler-alpha", "version": "0.0.0", "description": "The CDK Construct Library for Amazon Scheduler", "main": "lib/index.js", From bd7d7a1b0cebd3bea8befb0fab418695637026c5 Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Mon, 15 May 2023 08:27:11 +0100 Subject: [PATCH 15/21] Add rosetta default package --- .../aws-scheduler-alpha/rosetta/default.ts-fixture | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 packages/@aws-cdk/aws-scheduler-alpha/rosetta/default.ts-fixture diff --git a/packages/@aws-cdk/aws-scheduler-alpha/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-scheduler-alpha/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..30bc335fc331f --- /dev/null +++ b/packages/@aws-cdk/aws-scheduler-alpha/rosetta/default.ts-fixture @@ -0,0 +1,11 @@ +// Fixture with packages imported, but nothing else +import * as cdk from 'aws-cdk-lib'; +import * as scheduler from '@aws-cdk/aws-scheduler-alpha'; +import { Construct } from 'constructs'; + +class Fixture extends cdk.Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + /// here + } +} From 60dcfd1ec69089dbbb8c9cf710b487aa99cbc559 Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Mon, 15 May 2023 10:41:13 +0000 Subject: [PATCH 16/21] Update readme and fixtures to fix rosetta failures --- .../@aws-cdk/aws-scheduler-alpha/README.md | 34 ++++++++----------- .../rosetta/default.ts-fixture | 8 ++++- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/README.md b/packages/@aws-cdk/aws-scheduler-alpha/README.md index e80fd2b75eee0..f0f23d1d6a4dd 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/README.md +++ b/packages/@aws-cdk/aws-scheduler-alpha/README.md @@ -33,11 +33,12 @@ with EventBridge Scheduler, you apply tags to schedule groups, not to individual This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. It allows you to define Event Bridge Schedules. - ## Defining a schedule ```ts -const target = new targets.LambdaInvoke(props.func, { +declare const lambdaFunc: lambda.Function; + +const target = new targets.LambdaInvoke(lambdaFunc, { input: ScheduleTargetInput.fromObject({ "payload": "useful" }) @@ -83,7 +84,7 @@ and time zone in which EventBridge Scheduler evaluates the schedule. ```ts const oneTimeSchedule = new Schedule(this, 'Schedule', { scheduleExpression: ScheduleExpression.at( - new Date(2022, 10, 20, 19, 20, 23) + new Date(2022, 10, 20, 19, 20, 23), TimeZone.AMERICA_NEW_YORK ) target, @@ -106,7 +107,7 @@ const group = new Group(this, "Group", { groupName: "MyGroup" }); -const target = new targets.LambdaInvoke(props.func, { +const target = new targets.LambdaInvoke(func, { input: ScheduleTargetInput.fromObject({ "payload": "useful" }) @@ -196,7 +197,7 @@ to the target. See [full list of supported context attributes](https://docs.aws. ```ts const text = `Attempt number: ${ContextAttribute.attemptNumber}`; -const input = scheduler.ScheduleTargetInput.fromInput(text); +const input = ScheduleTargetInput.fromInput(text); ``` @@ -210,8 +211,6 @@ will grant minimal required permissions. For example: for invoking Lambda functi execution IAM role permission to `lambda:InvokeFunction`. ```ts -import * as iam from '@aws-cdk/aws-iam'; - declare const fn: lambda.Function; const role = new iam.Role(this, 'Role', { @@ -238,7 +237,7 @@ const target = new targets.Universal('sqs', 'CreateQueue', { input: input }); target.role.addToPolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, - resources: '*', + resources: ['*'], actions: ['sqs:CreateQueue'] })); @@ -263,8 +262,6 @@ to its target. Target classes will automatically add AWS KMS Decrypt permission permissions policy ```ts -import * as kms from '@aws-cdk/aws-kms'; - const key = new kms.Key(this, 'Key'); const schedule = new Schedule(this, 'Schedule', { @@ -291,7 +288,7 @@ If you've configured a retry policy for your schedule, EventBridge Scheduler del exhausting the maximum number of retries you set in the retry policy. ```ts -const dlq = new Queue(this, "DLQ", { +const dlq = new sqs.Queue(this, "DLQ", { queueName: 'MyDLQ', }); @@ -341,13 +338,11 @@ EventBridge Scheduler publishes additional metrics when your schedule exhausts i Class `Schedule` provides static methods for accessing all schedules metrics with default configuration, such as `metricAllErrors` for viewing errors when executing targets. -```ts - -import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; - -new Alarm(this, 'SchedulesErrorAlarm', { +```ts +new cloudwatch.Alarm(this, 'SchedulesErrorAlarm', { metric: Schedule.metricAllErrors(), - threshold: 0 + threshold: 0, + evaluationPeriods: 5 }); ``` @@ -360,9 +355,10 @@ const group = new Group(this, "Group", { groupName: "MyGroup" }); -new Alarm(this, 'MyGroupErrorAlarm', { +new cloudwatch.Alarm(this, 'MyGroupErrorAlarm', { metric: group.metricAllErrors(), - threshold: 0 + threshold: 0, + evaluationPeriods: 5 }); ``` diff --git a/packages/@aws-cdk/aws-scheduler-alpha/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-scheduler-alpha/rosetta/default.ts-fixture index 30bc335fc331f..71131d04c63a3 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/aws-scheduler-alpha/rosetta/default.ts-fixture @@ -1,7 +1,13 @@ // Fixture with packages imported, but nothing else import * as cdk from 'aws-cdk-lib'; -import * as scheduler from '@aws-cdk/aws-scheduler-alpha'; import { Construct } from 'constructs'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import * as sqs from 'aws-cdk-lib/aws-sqs'; +import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch'; +import { App, Stack, TimeZone, Duration } from 'aws-cdk-lib'; +import { ScheduleExpression } from '@aws-cdk/aws-scheduler-alpha'; class Fixture extends cdk.Stack { constructor(scope: Construct, id: string) { From e071c269a0d0553574a1162e0007103244b27911 Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Mon, 15 May 2023 10:43:06 +0000 Subject: [PATCH 17/21] Reformat the file --- .../aws-scheduler-alpha/lib/schedule-expression.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts index ae596d5b2ac2d..89aa1f9205dae 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts +++ b/packages/@aws-cdk/aws-scheduler-alpha/lib/schedule-expression.ts @@ -1,7 +1,6 @@ import { Duration, TimeZone } from 'aws-cdk-lib'; import * as events from 'aws-cdk-lib/aws-events'; - /** * ScheduleExpression for EventBridge Schedule * @@ -58,15 +57,16 @@ export abstract class ScheduleExpression { } /** - * Retrieve the expression for this schedule - */ + * Retrieve the expression for this schedule + */ public abstract readonly expressionString: string; + /** - * Retrieve the expression for this schedule - */ + * Retrieve the expression for this schedule + */ public abstract readonly timeZone?: TimeZone; - protected constructor() {}; + protected constructor() {} } /** From 260372b7fb5ec2a133374f7b5c8eb11941d00fff Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Mon, 15 May 2023 10:47:32 +0000 Subject: [PATCH 18/21] Turn back on eslint rules --- packages/@aws-cdk/aws-scheduler-alpha/.eslintrc.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/.eslintrc.js b/packages/@aws-cdk/aws-scheduler-alpha/.eslintrc.js index b284f20df26e9..2a2c7498774d0 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/.eslintrc.js +++ b/packages/@aws-cdk/aws-scheduler-alpha/.eslintrc.js @@ -1,8 +1,6 @@ const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; -baseConfig.rules['import/no-extraneous-dependencies'] = ['error', { devDependencies: true, peerDependencies: true } ]; -baseConfig.rules['import/order'] = 'off'; -baseConfig.rules['@aws-cdk/invalid-cfn-imports'] = 'off'; +baseConfig.rules['import/no-extraneous-dependencies'] = ['error', { devDependencies: true, peerDependencies: true }]; module.exports = baseConfig; From 30c87874c155f70e6f56127d33f4736abfe946de Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Tue, 16 May 2023 15:51:54 +0100 Subject: [PATCH 19/21] Remove sections for not yet implemented content --- .../@aws-cdk/aws-scheduler-alpha/README.md | 266 ++---------------- 1 file changed, 18 insertions(+), 248 deletions(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/README.md b/packages/@aws-cdk/aws-scheduler-alpha/README.md index f0f23d1d6a4dd..e86e835628d5e 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/README.md +++ b/packages/@aws-cdk/aws-scheduler-alpha/README.md @@ -35,21 +35,7 @@ This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aw ## Defining a schedule -```ts -declare const lambdaFunc: lambda.Function; - -const target = new targets.LambdaInvoke(lambdaFunc, { - input: ScheduleTargetInput.fromObject({ - "payload": "useful" - }) -}); - -const schedule = new Schedule(this, 'Schedule', { - scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), - target, - description: 'This is a test schedule that invokes lambda function every 10 minutes.', -}); -``` +TODO: Schedule is not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) ### Schedule Expressions @@ -58,7 +44,11 @@ You can choose from three schedule types when configuring your schedule: rate-ba Both rate-based and cron-based schedules are recurring schedules. You can configure each recurring schedule type using a schedule expression. For cron-based schedule you can specify a time zone in which EventBridge Scheduler evaluates the expression. -```ts + +> ScheduleExpression should be used together with class Schedule, which is not yet implemented. +> TODO: Switch to `ts` once Schedule is implemented + +```text const rateBasedSchedule = new Schedule(this, 'Schedule', { scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), target, @@ -81,7 +71,9 @@ const cronBasedSchedule = new Schedule(this, 'Schedule', { A one-time schedule is a schedule that invokes a target only once. You configure a one-time schedule when by specifying the time of the day, date, and time zone in which EventBridge Scheduler evaluates the schedule. -```ts +> TODO: Switch to `ts` once Schedule i implemented + +```text const oneTimeSchedule = new Schedule(this, 'Schedule', { scheduleExpression: ScheduleExpression.at( new Date(2022, 10, 20, 19, 20, 23), @@ -94,158 +86,20 @@ const oneTimeSchedule = new Schedule(this, 'Schedule', { ### Grouping Schedules -Your AWS account comes with a default scheduler group, which you can access in CDK with: - -```ts -const defaultGroup = Group.fromDefaultGroup(this, "DefaultGroup"); -``` - -When creating a new schedule, you can also add the schedule to a custom scheduling group managed by you: - -```ts -const group = new Group(this, "Group", { - groupName: "MyGroup" -}); - -const target = new targets.LambdaInvoke(func, { - input: ScheduleTargetInput.fromObject({ - "payload": "useful" - }) -}); - -const schedule1 = new Schedule(this, 'Schedule1', { - scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), - target -}); - -const schedule2 = new Schedule(this, 'Schedule2', { - scheduleExpression: ScheduleExpression.rate(Duration.minutes(5)), - target -}); - -group.addSchedules(schedule1, schedule2); - -// You can also assign groups in a schedule constructor: -const schedule3 = new Schedule(this, 'Schedule2', { - scheduleExpression: ScheduleExpression.rate(Duration.minutes(5)), - group, - target -}); -``` +TODO: Group is not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) ## Scheduler Targets -The `@aws-cdk/aws-schedule-targets` module includes classes that implement the `IScheduleTarget` interface for various AWS services. -EventBridge Scheduler supports two types of targets: templated targets invoke common API operations across a core groups of services, -and customizeable universal targets that you can use to call more than 6,000 operations across over 270 services. - -Templated targets are a set of common API operations across a group of core AWS services such as Amazon SQS, Lambda, and Step Functions. -The module contains CDK constructs for templated targets. For example, you can use construct `targets.LambdaInvoke` to target Lambda's Invoke API -operation by providing a `lambda.IFunction`, or use `targets.SqsSendMessage` with a `sqs.IQueue` to send a message to SQS queue. - - -The following templated targets are supported: - -1. `targets.CodeBuildStartBuild`: Start an AWS CodeBuild build -1. `targets.CodePipelineStartPipelineExecution`: Start an AWS CodePipeline pipeline execution -1. `targets.StepFunctionsStartExecution`: Trigger an AWS Step Functions state machine -1. `targets.KinesisDataFirehosePutRecord`: Put a record to a Kinesis Firehose -1. `targets.KinesisStreamPutRecord`: Put a record to a Kinesis Stream -1. `targets.InspectorStartAssessmentRun`: Start an AWS Inspector assessment run -1. `targets.EventBridgePutEvents`: Put an event to an AWS Event Bridge Event Bus -1. `targets.EcsTask`: Start a task on an Amazon ECS cluster -1. `targets.SageMakerStartPipelineExecution`: Start Amazon SageMaker pipeline -1. `targets.LambdaInvoke`: Invoke an AWS Lambda function -1. `targets.SqsSendMessage`: Send a message to an Amazon SQS Queue -1. `targets.SnsPublish`: Publish a message into an SNS topic - - -A universal target is a customizable set of parameters that allow you to invoke a wider set of API operation for many AWS services. -To create a universal target you need to specify `input`, service name and service action. See -[full list of support universal targets](https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html#supported-universal-targets). - -For example, to create a schedule that will create a SQS queue every hour: - -```ts -const input = ScheduleTargetInput.fromObject({ - 'QueueName': 'MyQueue' -}); - -const schedule = new Schedule(this, 'Schedule', { - scheduleExpression: ScheduleExpression.rate(Duration.hours(1)), - target: new targets.Universal('sqs', 'CreateQueue', { input: input }) -}); -``` +TODO: Scheduler Targets Module is not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) ### Input -Target can be invoked with a custom input. Class `ScheduleTargetInput` supports free form text input and JSON-formatted object input: - -```ts -const input = ScheduleTargetInput.fromObject({ - 'QueueName': 'MyQueue' -}); -``` - -You can include context attributes in your target payload. EventBridge Scheduler will replace each keyword with its respective value and deliver it -to the target. See [full list of supported context attributes](https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-schedule-context-attributes.html): - -1. `ContextAttribute.scheduleArn()` – The ARN of the schedule. -2. `ContextAttribute.scheduledTime()` – The time you specified for the schedule to invoke its target, for example, 2022-03-22T18:59:43Z. -3. `ContextAttribute.executionId()` – The unique ID that EventBridge Scheduler assigns for each attempted invocation of a target, for example d32c5kddcf5bb8c3. -4. `ContextAttribute.attemptNumber()` – A counter that identifies the attempt number for the current invocation, for example, 1. - -```ts -const text = `Attempt number: ${ContextAttribute.attemptNumber}`; -const input = ScheduleTargetInput.fromInput(text); -``` +TODO: Target Input is not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) ### Specifying Execution Role -An execution role is an IAM role that EventBridge Scheduler assumes in order to interact with other AWS services on your behalf. - -The classes for templated schedule targets automatically create an IAM role with all the minimum necessary -permissions to interact with the templated target. If you wish you may specify your own IAM role, then the templated targets -will grant minimal required permissions. For example: for invoking Lambda function target `LambdaInvoke` will grant -execution IAM role permission to `lambda:InvokeFunction`. - -```ts -declare const fn: lambda.Function; - -const role = new iam.Role(this, 'Role', { - assumedBy: new iam.ServicePrincipal('scheduler.amazonaws.com'), -}); - -const target = new targets.LambdaInvoke({ - input: ScheduleTargetInput.fromObject({ - "payload": "useful" - }), - role, -}, fn); -``` - -Universal target automatically create an IAM role if you do not specify your own IAM role. However, in comparison with templated targets, -for universal targets you must grant the required IAM permissions yourself. - -```ts -const input = ScheduleTargetInput.fromObject({ - 'QueueName': 'MyQueue' -}); - -const target = new targets.Universal('sqs', 'CreateQueue', { input: input }); - -target.role.addToPolicy(new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, - resources: ['*'], - actions: ['sqs:CreateQueue'] -})); - -const schedule = new Schedule(this, 'Schedule', { - scheduleExpression: ScheduleExpression.rate(Duration.hours(1)), - target -}); -``` +TODO: Not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) ### Cross-account and cross-region targets @@ -253,77 +107,16 @@ Executing cross-account and cross-region targets are not supported yet. ### Specifying Encryption key -EventBridge Scheduler integrates with AWS Key Management Service (AWS KMS) to encrypt and decrypt your data using an AWS KMS key. -EventBridge Scheduler supports two types of KMS keys: AWS owned keys, and customer managed keys. - -By default, all events in Scheduler are encrypted with a key that AWS owns and manages. -If you wish you can also provide a customer managed key to encrypt and decrypt the payload that your schedule delivers -to its target. Target classes will automatically add AWS KMS Decrypt permission to your schedule's execution role -permissions policy - -```ts -const key = new kms.Key(this, 'Key'); - -const schedule = new Schedule(this, 'Schedule', { - scheduleExpression: ScheduleExpression.rate(Duration.minutes(10)), - target, - key: key, -}); -``` - -See: [Data Protection](https://docs.aws.amazon.com/scheduler/latest/UserGuide/data-protection.html) in -the *Amazon EventBridge Scheduler User Guide*. +TODO: Not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) ## Error-handling -You can configure how your schedule handles failures, when EventBridge Scheduler is unable to deliver an event -successfully to a target, by using two primary mechanisms: a retry policy, and a dead-letter queue (DLQ). - -A retry policy determines the number of times EventBridge Scheduler must retry a failed event, and how long -to keep an unprocessed event. - -A DLQ is a standard Amazon SQS queue EventBridge Scheduler uses to deliver failed events to, after the retry -policy has been exhausted. You can use a DLQ to troubleshoot issues with your schedule or its downstream target. -If you've configured a retry policy for your schedule, EventBridge Scheduler delivers the dead-letter event after -exhausting the maximum number of retries you set in the retry policy. - -```ts -const dlq = new sqs.Queue(this, "DLQ", { - queueName: 'MyDLQ', -}); - -const target = new targets.LambdaInvoke(props.func, { - deadLetterQueue: dlq, - maximumEventAge: Duration.minutes(1), - maximumRetryAttempts: 3 -}); -``` +TODO: Not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) ## Overriding Target Properties -If you wish to reuse the same target in multiple schedules, you can override target properties -like `input`, `maximumRetryAttempts` and `maximumEventAge` when creating a Schedule: +TODO: Not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) -```ts -const target = new targets.LambdaInvoke(props.func, { - input: ScheduleTargetInput.fromObject({ - "payload": "useful" - }), -}); - -const schedule1 = new Schedule(this, 'Schedule', { - scheduleExpression: ScheduleExpression.cron({ day: '20' }), - target, -}); - -const schedule2 = new Schedule(this, 'Schedule2', { - scheduleExpression: ScheduleExpression.cron({ day: '5' }) - target, - targetOverrides: { - input: ScheduleTargetInput.fromText("Overriding Target Input") - } -}); -``` ## Monitoring @@ -335,31 +128,8 @@ EventBridge Scheduler publishes additional metrics when your schedule exhausts i ### Metrics for all schedules -Class `Schedule` provides static methods for accessing all schedules metrics with default configuration, -such as `metricAllErrors` for viewing errors when executing targets. - -```ts -new cloudwatch.Alarm(this, 'SchedulesErrorAlarm', { - metric: Schedule.metricAllErrors(), - threshold: 0, - evaluationPeriods: 5 -}); -``` +TODO: Not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) ### Metrics for a Group -To view metrics for a specific group you can use methods on class `Group`: - -```ts -const group = new Group(this, "Group", { - groupName: "MyGroup" -}); - -new cloudwatch.Alarm(this, 'MyGroupErrorAlarm', { - metric: group.metricAllErrors(), - threshold: 0, - evaluationPeriods: 5 -}); -``` - -See full list of metrics and their description at [Monitoring Using CloudWatch Metrics](https://docs.aws.amazon.com/scheduler/latest/UserGuide/monitoring-cloudwatch.html) in the *AWS Event Bridge Scheduler User Guide*. +TODO: Not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) From e874e34dfde1c323b65bc5f874dc5fa6e5e7746f Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Tue, 16 May 2023 23:45:32 +0100 Subject: [PATCH 20/21] Update @types/jest library version --- packages/@aws-cdk/aws-scheduler-alpha/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/package.json b/packages/@aws-cdk/aws-scheduler-alpha/package.json index 8d7f7956d3a0e..0dd7f971c0784 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/package.json +++ b/packages/@aws-cdk/aws-scheduler-alpha/package.json @@ -85,7 +85,7 @@ "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^29.5.0", + "@types/jest": "^29.5.1", "aws-cdk-lib": "0.0.0", "constructs": "^10.0.0" }, @@ -116,4 +116,4 @@ "assert/assert-dependency" ] } -} +} \ No newline at end of file From 2ab1af04762d0bf0d6c8661e952183c3cd683347 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> Date: Wed, 17 May 2023 15:42:18 -0400 Subject: [PATCH 21/21] Update README.md --- packages/@aws-cdk/aws-scheduler-alpha/README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk/aws-scheduler-alpha/README.md b/packages/@aws-cdk/aws-scheduler-alpha/README.md index e86e835628d5e..171cecdf66854 100644 --- a/packages/@aws-cdk/aws-scheduler-alpha/README.md +++ b/packages/@aws-cdk/aws-scheduler-alpha/README.md @@ -33,6 +33,8 @@ with EventBridge Scheduler, you apply tags to schedule groups, not to individual This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. It allows you to define Event Bridge Schedules. +> This module is in active development. Some features may not be implemented yet. + ## Defining a schedule TODO: Schedule is not yet implemented. See section in [L2 Event Bridge Scheduler RFC](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0474-event-bridge-scheduler-l2.md) @@ -46,7 +48,8 @@ cron-based schedule you can specify a time zone in which EventBridge Scheduler e > ScheduleExpression should be used together with class Schedule, which is not yet implemented. -> TODO: Switch to `ts` once Schedule is implemented + +[comment]: <> (TODO: Switch to `ts` once Schedule is implemented) ```text const rateBasedSchedule = new Schedule(this, 'Schedule', { @@ -61,7 +64,7 @@ const cronBasedSchedule = new Schedule(this, 'Schedule', { hour: '23', day: '20', month: '11', - timeZone: TimeZone.AMERICA_NEW_YORK + timeZone: TimeZone.AMERICA_NEW_YORK, }), target, description: 'This is a test cron-based schedule that will run at 11:00 PM, on day 20 of the month, only in November in New York timezone', @@ -71,14 +74,14 @@ const cronBasedSchedule = new Schedule(this, 'Schedule', { A one-time schedule is a schedule that invokes a target only once. You configure a one-time schedule when by specifying the time of the day, date, and time zone in which EventBridge Scheduler evaluates the schedule. -> TODO: Switch to `ts` once Schedule i implemented +[comment]: <> (TODO: Switch to `ts` once Schedule is implemented) ```text const oneTimeSchedule = new Schedule(this, 'Schedule', { scheduleExpression: ScheduleExpression.at( new Date(2022, 10, 20, 19, 20, 23), - TimeZone.AMERICA_NEW_YORK - ) + TimeZone.AMERICA_NEW_YORK, + ), target, description: 'This is a one-time schedule in New York timezone', });