Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(synthetics): add static cron method to schedule class #17250

Merged
merged 5 commits into from
Nov 2, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions packages/@aws-cdk/aws-synthetics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,15 @@ object to the `schedule` property.
Configure a run rate of up to 60 minutes with `Schedule.rate`:

```ts
Schedule.rate(Duration.minutes(5)), // Runs every 5 minutes.
Schedule.rate(Duration.minutes(5)) // Runs every 5 minutes.
```

You can also specify a [cron expression](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_cron.html) via `Schedule.expression`:
You can also specify a [cron expression](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_cron.html) with `Schedule.cron`:

```ts
Schedule.expression('cron(0 0,8,16 * * ? *)'), // Run at 12am, 8am, 4pm UTC every day
Schedule.cron({
hour: '0,8,16' // Run at 12am, 8am, 4pm UTC every day
})
```

If you want the canary to run just once upon deployment, you can use `Schedule.once()`.
Expand Down
72 changes: 72 additions & 0 deletions packages/@aws-cdk/aws-synthetics/lib/schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,81 @@ export class Schedule {
return new Schedule(`rate(${minutes} minutes)`);
}

/**
* Create a schedule from a set of cron fields
*/
public static cron(options: CronOptions): Schedule {
if (options.weekDay !== undefined && options.day !== undefined) {
throw new Error('Cannot supply both \'day\' and \'weekDay\', use at most one');
}

const minute = fallback(options.minute, '*');
const hour = fallback(options.hour, '*');
const month = fallback(options.month, '*');

// Weekday defaults to '?' if not supplied. If it is supplied, day must become '?'
const day = fallback(options.day, options.weekDay !== undefined ? '?' : '*');
const weekDay = fallback(options.weekDay, '?');

// '*' is only allowed in the year field
const year = '*';

return new Schedule(`cron(${minute} ${hour} ${day} ${month} ${weekDay} ${year})`);
}

private constructor(
/**
* The Schedule expression
*/
public readonly expressionString: string) {}
}


/**
* 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/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_cron.html
*/
export interface CronOptions {
/**
* The minute to run this rule at
*
* @default - Every minute
*/
readonly minute?: string;

/**
* The hour to run this rule at
*
* @default - Every hour
*/
readonly hour?: string;

/**
* The day of the month to run this rule at
*
* @default - Every day of the month
*/
readonly day?: string;

/**
* The month to run this rule at
*
* @default - Every month
*/
readonly month?: string;

/**
* The day of the week to run this rule at
*
* @default - Any day of the week
*/
readonly weekDay?: string;
}

function fallback(x: string | undefined, def: string): string {
return x ?? def;
}
21 changes: 21 additions & 0 deletions packages/@aws-cdk/aws-synthetics/test/canary.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,27 @@ test('Schedule can be set to 1 minute', () => {
});
});

test('Schedule can be set with Cron', () => {
// GIVEN
const stack = new Stack();

// WHEN
new synthetics.Canary(stack, 'Canary', {
schedule: synthetics.Schedule.cron({ minute: '30' }),
test: synthetics.Test.custom({
handler: 'index.handler',
code: synthetics.Code.fromInline('/* Synthetics handler code */'),
}),
runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_3,
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::Synthetics::Canary', {
Schedule: Match.objectLike({ Expression: 'cron(30 * * * ? *)' }),
});
});


test('Schedule can be set with Expression', () => {
// GIVEN
const stack = new Stack();
Expand Down
26 changes: 26 additions & 0 deletions packages/@aws-cdk/aws-synthetics/test/schedule.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as synthetics from '../lib';

describe('cron', () => {
test('day and weekDay are mutex: given week day', () => {
expect(synthetics.Schedule.cron({
weekDay: 'MON-FRI',
}).expressionString).toEqual('cron(* * ? * MON-FRI *)');
});

test('day and weekDay are mutex: given month day', () => {
expect(synthetics.Schedule.cron({
day: '1',
}).expressionString).toEqual('cron(* * 1 * ? *)');
});

test('day and weekDay are mutex: given neither', () => {
expect(synthetics.Schedule.cron({}).expressionString).toEqual('cron(* * * * ? *)');
});

test('day and weekDay are mutex: throw if given both', () => {
expect(() => synthetics.Schedule.cron({
day: '1',
weekDay: 'MON',
})).toThrow('Cannot supply both \'day\' and \'weekDay\', use at most one');
});
});