Skip to content

Commit

Permalink
feat(Config Schema): Schema for AWS schedule event (#8143)
Browse files Browse the repository at this point in the history
  • Loading branch information
andyjduncan authored and medikoo committed Sep 9, 2020
1 parent 51a10aa commit d9b91e9
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 326 deletions.
110 changes: 55 additions & 55 deletions lib/plugins/aws/package/compile/events/schedule/index.js
Expand Up @@ -2,8 +2,9 @@

const _ = require('lodash');

const rateSyntaxPattern = /^rate\((?:1 (?:minute|hour|day)|(?:1\d+|[2-9]\d*) (?:minute|hour|day)s)\)$/;
const cronSyntaxPattern = /^cron\(\S+ \S+ \S+ \S+ \S+ \S+\)$/;
const rateSyntax = '^rate\\((?:1 (?:minute|hour|day)|(?:1\\d+|[2-9]\\d*) (?:minute|hour|day)s)\\)$';
const cronSyntax = '^cron\\(\\S+ \\S+ \\S+ \\S+ \\S+ \\S+\\)$';
const scheduleSyntax = `${rateSyntax}|${cronSyntax}`;

class AwsCompileScheduledEvents {
constructor(serverless) {
Expand All @@ -14,22 +15,60 @@ class AwsCompileScheduledEvents {
'package:compileEvents': this.compileScheduledEvents.bind(this),
};

// TODO: Complete schema, see https://github.com/serverless/serverless/issues/8032
this.serverless.configSchemaHandler.defineFunctionEvent('aws', 'schedule', {
anyOf: [{ type: 'string' }, { type: 'object' }],
oneOf: [
{ type: 'string', pattern: scheduleSyntax },
{
type: 'object',
properties: {
rate: { type: 'string', pattern: scheduleSyntax },
enabled: { type: 'boolean' },
name: { type: 'string', minLength: 1, maxLength: 64, pattern: '[\\.\\-_A-Za-z0-9]+' },
description: { type: 'string', maxLength: 512 },
input: {
oneOf: [
{ type: 'string', maxLength: 8192 },
{
type: 'object',
oneOf: [
{
properties: {
body: { type: 'string', maxLength: 8192 },
},
required: ['body'],
additionalProperties: false,
},
{
not: {
required: ['body'],
},
},
],
},
],
},
inputPath: { type: 'string', maxLength: 256 },
inputTransformer: {
type: 'object',
properties: {
inputTemplate: {
type: 'string',
minLength: 1,
maxLength: 8192,
},
inputPathsMap: { type: 'object' },
},
required: ['inputTemplate'],
additionalProperties: false,
},
},
required: ['rate'],
additionalProperties: false,
},
],
});
}

buildValidationErrorMessage(functionName) {
return [
`"rate" property for schedule event is missing or invalid in function ${functionName}.`,
' The correct syntax is: `schedule: rate(10 minutes)`, `schedule: cron(0 12 * * ? *)`',
' OR an object with "rate" property.',
' Please check the docs for more info:',
' https://serverless.com/framework/docs/providers/aws/events/schedule/',
].join('');
}

compileScheduledEvents() {
this.serverless.service.getAllFunctions().forEach(functionName => {
const functionObj = this.serverless.service.getFunction(functionName);
Expand All @@ -48,10 +87,6 @@ class AwsCompileScheduledEvents {
let Description;

if (typeof event.schedule === 'object') {
if (!this.validateScheduleSyntax(event.schedule.rate)) {
const errorMessage = this.buildValidationErrorMessage(functionName);
throw new this.serverless.classes.Error(errorMessage);
}
ScheduleExpression = event.schedule.rate;
State = 'ENABLED';
if (event.schedule.enabled === false) {
Expand All @@ -63,29 +98,9 @@ class AwsCompileScheduledEvents {
Name = event.schedule.name;
Description = event.schedule.description;

const inputOptions = [Input, InputPath, InputTransformer].filter(i => i);
if (inputOptions.length > 1) {
const errorMessage = [
'You can only set one of input, inputPath, or inputTransformer ',
'properties at the same time for schedule events. ',
'Please check the AWS docs for more info',
].join('');
throw new this.serverless.classes.Error(errorMessage);
}

if (Input && typeof Input === 'object') {
if (typeof Input.body === 'string') {
try {
Input.body = JSON.parse(Input.body);
} catch (error) {
const errorMessage = [
'The body of the schedule event associated with',
` ${functionName} was passed as a string`,
' but it failed to parse to a JSON object.',
' Please check the docs for more info.',
].join('');
throw new this.serverless.classes.Error(errorMessage);
}
Input.body = JSON.parse(Input.body);
}
Input = JSON.stringify(Input);
}
Expand All @@ -96,12 +111,9 @@ class AwsCompileScheduledEvents {
if (InputTransformer) {
InputTransformer = this.formatInputTransformer(InputTransformer);
}
} else if (this.validateScheduleSyntax(event.schedule)) {
} else {
ScheduleExpression = event.schedule;
State = 'ENABLED';
} else {
const errorMessage = this.buildValidationErrorMessage(functionName);
throw new this.serverless.classes.Error(errorMessage);
}

const lambdaLogicalId = this.provider.naming.getLambdaLogicalId(functionName);
Expand Down Expand Up @@ -165,19 +177,7 @@ class AwsCompileScheduledEvents {
});
}

validateScheduleSyntax(input) {
return (
typeof input === 'string' && (rateSyntaxPattern.test(input) || cronSyntaxPattern.test(input))
);
}

formatInputTransformer(inputTransformer) {
if (!inputTransformer.inputTemplate) {
throw new this.serverless.classes.Error(
'The inputTemplate key is required when specifying an ' +
'inputTransformer for a schedule event'
);
}
const cfmOutput = {
// InputTemplate is required
InputTemplate: inputTransformer.inputTemplate,
Expand Down

0 comments on commit d9b91e9

Please sign in to comment.