UNPKG

cloud-red

Version:

Harnessing Serverless for your cloud integration needs

158 lines (139 loc) 4.77 kB
module.exports = function(RED) { 'use strict'; const claudia = require('claudia'); const AWS = require('aws-sdk'); const path = require('path'); /** * Constructs an s3trigger * @param {Object} props - S3 trigger properties * @param {string} props.name - node label to be used * @param {string} props.bucketName - S3 Bucket name which will push notifications to Lambda * @param {string} props.prefix - (optional) Prefix filter for S3 keys that will cause the event * @param {string} props.suffix - (optional) Suffix filter for S3 keys that will cause the event * @param {string} props.version - (optional) Bind to a particular version. Defaults to: `latest` version * @param {string} props.events - (optional) Comma separated list of event types that trigger the function. Defaults to: `s3:ObjectCreated:*` * @param {string} props.description - (optional) General Description about this trigger * */ class S3Trigger { constructor(props) { RED.nodes.createNode(this, props); this.name = props.name; this.bucketName = props.bucketName; this.prefix = props.prefix; this.suffix = props.suffix; this.version = props.version; this.events = props.events; this.description = props.description; this.postEditorDeployment = this.postEditorDeployment.bind(this); RED.events.on('editor:post-deployment', this.postEditorDeployment); this.on('close', () => { // this.log('Removing listener'); RED.events.removeListener( 'editor:post-deployment', this.postEditorDeployment ); }); } async getBucketNotifications(s3EventOpts) { // Make sure the following event is not registered in the bucket let events = this.events ? this.events.split(',') : ['s3:ObjectCreated:*']; AWS.config.credentials = new AWS.SharedIniFileCredentials({ profile: 'personal' }); try { const s3 = new AWS.S3(); const config = await s3 .getBucketNotificationConfiguration({ Bucket: s3EventOpts.bucket }) .promise(); const exist = this.checkIfEventsExist( config.LambdaFunctionConfigurations, events ); if (exist) { this.log('Removing existing S3 Event Notification ...'); const result = await s3 .putBucketNotificationConfiguration({ Bucket: s3EventOpts.bucket, NotificationConfiguration: {} }) .promise(); return result; } } catch (err) { console.log(err); throw err; } } checkIfEventsExist(lambdaConfigs, eventsToMatch) { if (!lambdaConfigs && lambdaConfigs.length === 0) { return false; } let BreakException = {}; // hack as there is no built-in ability to break in forEach. Js, c'mon!! let found = false; try { lambdaConfigs.forEach(configs => { if (!configs.Events && configs.Events.length === 0) { found = false; } else { configs.Events.forEach(event => { if (eventsToMatch.indexOf(event) >= 0) { // found it found = true; throw BreakException; } }); } }); } catch (error) { if (error !== BreakException) throw e; return found; } return found; } async postEditorDeployment() { //RED.settings.getUserSettings(); this.log('Attaching s3 event to lambda...'); const userDir = RED.settings.userDir; let s3EventOpts = { bucket: this.bucketName, // mandatory source: userDir, config: path.join(userDir, 'cloud-red-config.json') }; if (this.prefix) { s3EventOpts.prefix = this.prefix; } if (this.suffix) { s3EventOpts.suffix = this.suffix; } if (this.events) { s3EventOpts.events = this.events; } // Clean up bucket notification if exists try { await this.getBucketNotifications(s3EventOpts); } catch (err) { throw err; } AWS.config.credentials = new AWS.SharedIniFileCredentials({ profile: 'personal' }); claudia .addS3EventSource(s3EventOpts) .then(() => { this.log( `Lambda configured to receive S3 Event notification from bucket: ${this.bucketName}` ); }) .catch(err => { this.error('Error while attaching an S3 event to lambda'); console.log(err); }); } } RED.nodes.registerType('s3-trigger', S3Trigger); };