UNPKG

serverless

Version:

Serverless Framework - Build web, mobile and IoT applications with serverless architectures using AWS Lambda, Azure Functions, Google CloudFunctions & more

141 lines (125 loc) 5.31 kB
'use strict'; const _ = require('lodash'); class AwsCompileScheduledEvents { constructor(serverless) { this.serverless = serverless; this.provider = this.serverless.getProvider('aws'); this.hooks = { 'package:compileEvents': this.compileScheduledEvents.bind(this), }; } compileScheduledEvents() { this.serverless.service.getAllFunctions().forEach((functionName) => { const functionObj = this.serverless.service.getFunction(functionName); let scheduleNumberInFunction = 0; if (functionObj.events) { functionObj.events.forEach(event => { if (event.schedule) { scheduleNumberInFunction++; let ScheduleExpression; let State; let Input; let InputPath; let Name; let Description; // TODO validate rate syntax if (typeof event.schedule === 'object') { if (!event.schedule.rate) { const errorMessage = [ `Missing "rate" property for schedule event in function ${functionName}`, ' The correct syntax is: schedule: rate(10 minutes)', ' OR an object with "rate" property.', ' Please check the docs for more info.', ].join(''); throw new this.serverless.classes .Error(errorMessage); } ScheduleExpression = event.schedule.rate; State = 'ENABLED'; if (event.schedule.enabled === false) { State = 'DISABLED'; } Input = event.schedule.input; InputPath = event.schedule.inputPath; Name = event.schedule.name; Description = event.schedule.description; if (Input && InputPath) { const errorMessage = [ 'You can\'t set both input & inputPath 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') { Input = JSON.stringify(Input); } if (Input && typeof Input === 'string') { // escape quotes to favor JSON.parse Input = Input.replace(/\"/g, '\\"'); // eslint-disable-line } } else if (typeof event.schedule === 'string') { ScheduleExpression = event.schedule; State = 'ENABLED'; } else { const errorMessage = [ `Schedule event of function ${functionName} is not an object nor a string`, ' The correct syntax is: schedule: rate(10 minutes)', ' OR an object with "rate" property.', ' Please check the docs for more info.', ].join(''); throw new this.serverless.classes .Error(errorMessage); } const lambdaLogicalId = this.provider.naming .getLambdaLogicalId(functionName); const scheduleLogicalId = this.provider.naming .getScheduleLogicalId(functionName, scheduleNumberInFunction); const lambdaPermissionLogicalId = this.provider.naming .getLambdaSchedulePermissionLogicalId(functionName, scheduleNumberInFunction); const scheduleId = this.provider.naming.getScheduleId(functionName); const scheduleTemplate = ` { "Type": "AWS::Events::Rule", "Properties": { "ScheduleExpression": "${ScheduleExpression}", "State": "${State}", ${Name ? `"Name": "${Name}",` : ''} ${Description ? `"Description": "${Description}",` : ''} "Targets": [{ ${Input ? `"Input": "${Input}",` : ''} ${InputPath ? `"InputPath": "${InputPath}",` : ''} "Arn": { "Fn::GetAtt": ["${lambdaLogicalId}", "Arn"] }, "Id": "${scheduleId}" }] } } `; const permissionTemplate = ` { "Type": "AWS::Lambda::Permission", "Properties": { "FunctionName": { "Fn::GetAtt": ["${ lambdaLogicalId}", "Arn"] }, "Action": "lambda:InvokeFunction", "Principal": "events.amazonaws.com", "SourceArn": { "Fn::GetAtt": ["${scheduleLogicalId}", "Arn"] } } } `; const newScheduleObject = { [scheduleLogicalId]: JSON.parse(scheduleTemplate), }; const newPermissionObject = { [lambdaPermissionLogicalId]: JSON.parse(permissionTemplate), }; _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, newScheduleObject, newPermissionObject); } }); } }); } } module.exports = AwsCompileScheduledEvents;