import _ from 'lodash' import resolveLambdaTarget from '../../../utils/resolve-lambda-target.js' class AwsCompileIoTEvents { constructor(serverless) { this.serverless = serverless this.provider = this.serverless.getProvider('aws') this.hooks = { 'package:compileEvents': async () => this.compileIoTEvents(), } this.serverless.configSchemaHandler.defineFunctionEvent('aws', 'iot', { type: 'object', properties: { sql: { type: 'string', }, sqlVersion: { type: 'string', enum: ['2015-10-08', '2016-03-23', 'beta'], }, name: { type: 'string', }, enabled: { type: 'boolean', }, description: { type: 'string', }, }, required: ['sql'], additionalProperties: false, }) } compileIoTEvents() { this.serverless.service.getAllFunctions().forEach((functionName) => { const functionObj = this.serverless.service.getFunction(functionName) let iotNumberInFunction = 0 if (functionObj.events) { functionObj.events.forEach((event) => { if (event.iot) { iotNumberInFunction++ const ruleName = event.iot.name ? event.iot.name.replace(/\r?\n/g, '') : null const awsIotSqlVersion = event.iot.sqlVersion ? event.iot.sqlVersion.replace(/\r?\n/g, '') : null const description = event.iot.description ? event.iot.description.replace(/\r?\n/g, '') : null const sql = event.iot.sql.replace(/\r?\n/g, '') const ruleDisabled = event.iot.enabled === false const iotLogicalId = this.provider.naming.getIotLogicalId( functionName, iotNumberInFunction, ) const lambdaPermissionLogicalId = this.provider.naming.getLambdaIotPermissionLogicalId( functionName, iotNumberInFunction, ) const topicRuleResource = { Type: 'AWS::IoT::TopicRule', DependsOn: _.get(functionObj.targetAlias, 'logicalId'), Properties: { TopicRulePayload: { RuleDisabled: ruleDisabled, Sql: sql, Actions: [ { Lambda: { FunctionArn: resolveLambdaTarget( functionName, functionObj, ), }, }, ], }, }, } if (ruleName) { topicRuleResource.Properties.RuleName = ruleName } if (description) { topicRuleResource.Properties.TopicRulePayload.Description = description } if (awsIotSqlVersion) { topicRuleResource.Properties.TopicRulePayload.AwsIotSqlVersion = awsIotSqlVersion } const permissionResource = { Type: 'AWS::Lambda::Permission', DependsOn: _.get(functionObj.targetAlias, 'logicalId'), Properties: { FunctionName: resolveLambdaTarget(functionName, functionObj), Action: 'lambda:InvokeFunction', Principal: 'iot.amazonaws.com', SourceArn: { 'Fn::Join': [ '', [ 'arn:', { Ref: 'AWS::Partition' }, ':iot:', { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, ':rule/', { Ref: iotLogicalId }, ], ], }, }, } const newIotObject = { [iotLogicalId]: topicRuleResource, } const newPermissionObject = { [lambdaPermissionLogicalId]: permissionResource, } _.merge( this.serverless.service.provider.compiledCloudFormationTemplate .Resources, newIotObject, newPermissionObject, ) } }) } }) } } export default AwsCompileIoTEvents