diff --git a/index.js b/index.js index 6d2e1394..c9e939cd 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,9 @@ // For development/testing purposes exports.handler = function (event, context, callback) { - console.log('Running index.handler'); - console.log('=================================='); - console.log('event', event); - console.log('=================================='); - console.log('Stopping index.handler'); - callback(null); -}; + console.log('Running index.handler') + console.log('==================================') + console.log('event', event) + console.log('==================================') + console.log('Stopping index.handler') + callback(null) +} diff --git a/lib/main.js b/lib/main.js index a2ef5dc4..8a3e510e 100644 --- a/lib/main.js +++ b/lib/main.js @@ -1,97 +1,97 @@ -'use strict'; +'use strict' -var path = require('path'); -var aws = require('aws-sdk'); -var exec = require('child_process').exec; -var fs = require('fs-extra'); -var packageJson = require(path.join(__dirname, '..', 'package.json')); -var minimatch = require('minimatch'); -var async = require('async'); -var zip = new (require('node-zip'))(); -var dotenv = require('dotenv'); -var ScheduleEvents = require(path.join(__dirname, 'schedule_events')); +var path = require('path') +var aws = require('aws-sdk') +var exec = require('child_process').exec +var fs = require('fs-extra') +var packageJson = require(path.join(__dirname, '..', 'package.json')) +var minimatch = require('minimatch') +var async = require('async') +var zip = new (require('node-zip'))() +var dotenv = require('dotenv') +var ScheduleEvents = require(path.join(__dirname, 'schedule_events')) -var maxBufferSize = 50 * 1024 * 1024; +var maxBufferSize = 50 * 1024 * 1024 var Lambda = function () { - this.version = packageJson.version; + this.version = packageJson.version - return this; -}; + return this +} Lambda.prototype._createSampleFile = function (file, boilerplateName) { - var exampleFile = path.join(process.cwd(), file); + var exampleFile = path.join(process.cwd(), file) var boilerplateFile = path.join( __dirname, (boilerplateName || file) + '.example' - ); + ) if (!fs.existsSync(exampleFile)) { - fs.writeFileSync(exampleFile, fs.readFileSync(boilerplateFile)); - console.log(exampleFile + ' file successfully created'); + fs.writeFileSync(exampleFile, fs.readFileSync(boilerplateFile)) + console.log(exampleFile + ' file successfully created') } -}; +} Lambda.prototype.setup = function (program) { - console.log('Running setup.'); - this._createSampleFile('.env', '.env'); - this._createSampleFile(program.eventFile, 'event.json'); - this._createSampleFile('deploy.env', 'deploy.env'); - this._createSampleFile(program.contextFile, 'context.json'); - this._createSampleFile('event_sources.json', 'event_sources.json'); + console.log('Running setup.') + this._createSampleFile('.env', '.env') + this._createSampleFile(program.eventFile, 'event.json') + this._createSampleFile('deploy.env', 'deploy.env') + this._createSampleFile(program.contextFile, 'context.json') + this._createSampleFile('event_sources.json', 'event_sources.json') console.log('Setup done. Edit the .env, deploy.env, ' + program.contextFile + ' and ' + program.eventFile + - ' files as needed.'); -}; + ' files as needed.') +} Lambda.prototype.run = function (program) { - this._createSampleFile(program.eventFile, 'event.json'); - var splitHandler = program.handler.split('.'); - var filename = splitHandler[0] + '.js'; - var handlername = splitHandler[1]; + this._createSampleFile(program.eventFile, 'event.json') + var splitHandler = program.handler.split('.') + var filename = splitHandler[0] + '.js' + var handlername = splitHandler[1] // Set custom environment variables if program.configFile is defined if (program.configFile) { - this._setRunTimeEnvironmentVars(program); + this._setRunTimeEnvironmentVars(program) } - var handler = require(path.join(process.cwd(), filename))[handlername]; - var event = require(path.join(process.cwd(), program.eventFile)); - var context = require(path.join(process.cwd(), program.contextFile)); + var handler = require(path.join(process.cwd(), filename))[handlername] + var event = require(path.join(process.cwd(), program.eventFile)) + var context = require(path.join(process.cwd(), program.contextFile)) - this._runHandler(handler, event, program, context); -}; + this._runHandler(handler, event, program, context) +} Lambda.prototype._runHandler = function (handler, event, program, context) { - var startTime = new Date(); - var timeout = Math.min(program.timeout, 300) * 1000; // convert the timeout into milliseconds + var startTime = new Date() + var timeout = Math.min(program.timeout, 300) * 1000 // convert the timeout into milliseconds var callback = function (err, result) { if (err) { - process.exitCode = 255; - console.log('Error: ' + err); + process.exitCode = 255 + console.log('Error: ' + err) } else { - process.exitCode = 0; - console.log('Success:'); + process.exitCode = 0 + console.log('Success:') if (result) { - console.log(JSON.stringify(result)); + console.log(JSON.stringify(result)) } } if (context.callbackWaitsForEmptyEventLoop === false) { - process.exit(); + process.exit() } - }; + } context.getRemainingTimeInMillis = function () { - var currentTime = new Date(); - return timeout - (currentTime - startTime); - }; + var currentTime = new Date() + return timeout - (currentTime - startTime) + } if (['nodejs4.3', 'nodejs6.10'].indexOf(program.runtime) === -1) { - console.error(`Runtime [${program.runtime}] is not supported.`); - process.exit(254); + console.error(`Runtime [${program.runtime}] is not supported.`) + process.exit(254) } - handler(event, context, callback); -}; + handler(event, context, callback) +} Lambda.prototype._params = function (program, buffer) { var params = { @@ -121,20 +121,20 @@ Lambda.prototype._params = function (program, buffer) { TracingConfig: { Mode: null } - }; + } // Escape characters that is not allowed by AWS Lambda - params.FunctionName = params.FunctionName.replace(/[^a-zA-Z0-9-_]/g, '_'); + params.FunctionName = params.FunctionName.replace(/[^a-zA-Z0-9-_]/g, '_') if (program.vpcSubnets && program.vpcSecurityGroups) { params.VpcConfig = { 'SubnetIds': program.vpcSubnets.split(','), 'SecurityGroupIds': program.vpcSecurityGroups.split(',') - }; + } } if (program.configFile) { - var configValues = fs.readFileSync(program.configFile); - var config = dotenv.parse(configValues); + var configValues = fs.readFileSync(program.configFile) + var config = dotenv.parse(configValues) // If `configFile` is an empty file, `config` value will be `{}` params.Environment = { Variables: config @@ -143,48 +143,48 @@ Lambda.prototype._params = function (program, buffer) { if (program.deadLetterConfigTargetArn !== undefined) { params.DeadLetterConfig = { TargetArn: program.deadLetterConfigTargetArn - }; + } } if (program.tracingConfig) { - params.TracingConfig.Mode = program.tracingConfig; + params.TracingConfig.Mode = program.tracingConfig } - return params; -}; + return params +} Lambda.prototype._eventSourceList = function (program) { if (!program.eventSourceFile) { return { EventSourceMappings: null, ScheduleEvents: null - }; + } } const list = (function () { try { - return fs.readJsonSync(program.eventSourceFile); + return fs.readJsonSync(program.eventSourceFile) } catch (err) { - throw err; + throw err } - })(); + })() if (Object.prototype.toString.call(list) === '[object Array]') { // backward-compatible return { EventSourceMappings: list, ScheduleEvents: [] - }; + } } if (!list.EventSourceMappings) { - list.EventSourceMappings = []; + list.EventSourceMappings = [] } if (!list.ScheduleEvents) { - list.ScheduleEvents = []; + list.ScheduleEvents = [] } - return list; -}; + return list +} Lambda.prototype._fileCopy = function (program, src, dest, excludeNodeModules, callback) { - const srcAbsolutePath = path.resolve(src); + const srcAbsolutePath = path.resolve(src) const excludes = (function () { return [ '.git*', @@ -196,79 +196,79 @@ Lambda.prototype._fileCopy = function (program, src, dest, excludeNodeModules, c path.join(path.sep, 'build', path.sep) ] .concat(program.excludeGlobs ? program.excludeGlobs.split(' ') : []) - .concat(excludeNodeModules ? [path.join(path.sep, 'node_modules')] : []); - })(); + .concat(excludeNodeModules ? [path.join(path.sep, 'node_modules')] : []) + })() // Formatting for `filter` of `fs.copy` - const dirBlobs = []; + const dirBlobs = [] const pattern = '{' + excludes.map(function (str) { if (str.charAt(str.length - 1) === path.sep) { - str = str.substr(0, str.length - 1); - dirBlobs.push(str); + str = str.substr(0, str.length - 1) + dirBlobs.push(str) } if (str.charAt(0) === path.sep) { - return path.join(srcAbsolutePath, str); + return path.join(srcAbsolutePath, str) } if (str.indexOf(path.sep) >= 0) { - return path.join(path.resolve('/**'), str); + return path.join(path.resolve('/**'), str) } - return str; - }).join(',') + '}'; - const dirPatternRegExp = new RegExp(`(${dirBlobs.join('|')})$`); + return str + }).join(',') + '}' + const dirPatternRegExp = new RegExp(`(${dirBlobs.join('|')})$`) fs.mkdirs(dest, function (err) { if (err) { - return callback(err); + return callback(err) } const options = { dereference: true, // same meaning as `-L` of `rsync` command filter: function (src, dest) { if (!program.prebuiltDirectory && src === path.join(srcAbsolutePath, 'package.json')) { // include package.json unless prebuiltDirectory is set - return true; + return true } if (!minimatch(src, pattern, { matchBase: true })) { - return true; + return true } // Directory check. Even if `src` is a directory it will not end with '/'. if (!dirPatternRegExp.test(src)) { - return false; + return false } - return !fs.statSync(src).isDirectory(); + return !fs.statSync(src).isDirectory() } - }; + } fs.copy(src, dest, options, function (err) { if (err) { - return callback(err); + return callback(err) } - return callback(null, true); - }); - }); -}; + return callback(null, true) + }) + }) +} // `_rsync` will be replaced by` _fileCopy`. Lambda.prototype._rsync = function (program, src, dest, excludeNodeModules, callback) { - var excludes = ['.git*', '*.swp', '.editorconfig', '.lambda', 'deploy.env', '*.log', '/build/']; - var excludeGlobs = []; + var excludes = ['.git*', '*.swp', '.editorconfig', '.lambda', 'deploy.env', '*.log', '/build/'] + var excludeGlobs = [] if (program.excludeGlobs) { - excludeGlobs = program.excludeGlobs.split(' '); + excludeGlobs = program.excludeGlobs.split(' ') } var excludeArgs = excludeGlobs .concat(excludes) .concat(excludeNodeModules ? ['/node_modules'] : []) .map(function (exclude) { - return '--exclude=' + exclude; - }).join(' '); + return '--exclude=' + exclude + }).join(' ') fs.mkdirs(dest, function (err) { if (err) { - return callback(err); + return callback(err) } // include package.json unless prebuiltDirectory is set - var includeArgs = program.prebuiltDirectory ? '' : '--include /package.json '; + var includeArgs = program.prebuiltDirectory ? '' : '--include /package.json ' // we need the extra / after src to make sure we are copying the content // of the directory, not the directory itself. @@ -277,110 +277,110 @@ Lambda.prototype._rsync = function (program, src, dest, excludeNodeModules, call env: process.env }, function (err) { if (err) { - return callback(err); + return callback(err) } - return callback(null, true); - }); - }); -}; + return callback(null, true) + }) + }) +} Lambda.prototype._npmInstall = function (program, codeDirectory, callback) { const installOptions = [ `--prefix ${codeDirectory}`, process.platform === 'win32' ? `--cwd ${codeDirectory}` : null - ].join(' '); + ].join(' ') var command = program.dockerImage ? 'docker run --rm -v ' + codeDirectory + ':/var/task ' + program.dockerImage + ' npm -s install --production' - : `npm -s install --production ${installOptions}`; + : `npm -s install --production ${installOptions}` exec(command, { maxBuffer: maxBufferSize, env: process.env }, function (err) { if (err) { - return callback(err); + return callback(err) } - return callback(null, true); - }); -}; + return callback(null, true) + }) +} Lambda.prototype._postInstallScript = function (program, codeDirectory, callback) { - var scriptFilename = 'post_install.sh'; - var cmd = path.join(codeDirectory, scriptFilename) + ' ' + program.environment; + var scriptFilename = 'post_install.sh' + var cmd = path.join(codeDirectory, scriptFilename) + ' ' + program.environment - var filePath = path.join(codeDirectory, scriptFilename); + var filePath = path.join(codeDirectory, scriptFilename) if (!fs.existsSync(filePath)) { - return callback(null); + return callback(null) } - console.log('=> Running post install script ' + scriptFilename); + console.log('=> Running post install script ' + scriptFilename) exec(cmd, { env: process.env, cwd: codeDirectory, maxBuffer: maxBufferSize }, function (error, stdout, stderr) { if (error) { - return callback(new Error(`${error} stdout: ${stdout} stderr: ${stderr}`)); + return callback(new Error(`${error} stdout: ${stdout} stderr: ${stderr}`)) } - console.log('\t\t' + stdout); - callback(null); - }); -}; + console.log('\t\t' + stdout) + callback(null) + }) +} Lambda.prototype._zip = function (program, codeDirectory, callback) { var options = { type: 'nodebuffer', compression: 'DEFLATE' - }; + } - console.log('=> Zipping repo. This might take up to 30 seconds'); + console.log('=> Zipping repo. This might take up to 30 seconds') fs.walk(codeDirectory) .on('data', function (file) { if (!file.stats.isDirectory()) { - var content = fs.readFileSync(file.path); - var filePath = file.path.replace(path.join(codeDirectory, path.sep), ''); - zip.file(filePath, content); + var content = fs.readFileSync(file.path) + var filePath = file.path.replace(path.join(codeDirectory, path.sep), '') + zip.file(filePath, content) } }) .on('end', function () { - var data = zip.generate(options); - return callback(null, data); - }); -}; + var data = zip.generate(options) + return callback(null, data) + }) +} Lambda.prototype._codeDirectory = function () { - return path.resolve('.', '.lambda'); -}; + return path.resolve('.', '.lambda') +} Lambda.prototype._cleanDirectory = function (codeDirectory, callback) { fs.remove(codeDirectory, function (err) { if (err) { - throw err; + throw err } fs.mkdirs(codeDirectory, function (err) { if (err) { - throw err; + throw err } - return callback(null, true); - }); - }); -}; + return callback(null, true) + }) + }) +} Lambda.prototype._setRunTimeEnvironmentVars = function (program) { - var configValues = fs.readFileSync(program.configFile); - var config = dotenv.parse(configValues); + var configValues = fs.readFileSync(program.configFile) + var config = dotenv.parse(configValues) for (let k in config) { if (!config.hasOwnProperty(k)) { - continue; + continue } - process.env[k] = config[k]; + process.env[k] = config[k] } -}; +} Lambda.prototype._uploadExisting = function (lambda, params, cb) { var request = lambda.updateFunctionCode({ @@ -389,7 +389,7 @@ Lambda.prototype._uploadExisting = function (lambda, params, cb) { 'Publish': params.Publish }, function (err, data) { if (err) { - return cb(err, data); + return cb(err, data) } return lambda.updateFunctionConfiguration({ @@ -405,155 +405,155 @@ Lambda.prototype._uploadExisting = function (lambda, params, cb) { 'DeadLetterConfig': params.DeadLetterConfig, 'TracingConfig': params.TracingConfig }, function (err, data) { - return cb(err, data); - }); - }); + return cb(err, data) + }) + }) request.on('retry', function (response) { - console.log(response.error.message); - console.log('=> Retrying'); - }); + console.log(response.error.message) + console.log('=> Retrying') + }) - return request; -}; + return request +} Lambda.prototype._uploadNew = function (lambda, params, cb) { var request = lambda.createFunction(params, function (err, data) { - return cb(err, data); - }); + return cb(err, data) + }) request.on('retry', function (response) { - console.log(response.error.message); - console.log('=> Retrying'); - }); + console.log(response.error.message) + console.log('=> Retrying') + }) - return request; -}; + return request +} Lambda.prototype._readArchive = function (program, archiveCallback) { if (!fs.existsSync(program.deployZipfile)) { - var err = new Error('No such Zipfile [' + program.deployZipfile + ']'); - return archiveCallback(err); + var err = new Error('No such Zipfile [' + program.deployZipfile + ']') + return archiveCallback(err) } - fs.readFile(program.deployZipfile, archiveCallback); -}; + fs.readFile(program.deployZipfile, archiveCallback) +} Lambda.prototype._archive = function (program, archiveCallback) { if (program.deployZipfile && fs.existsSync(program.deployZipfile)) { - return this._readArchive(program, archiveCallback); + return this._readArchive(program, archiveCallback) } return program.prebuiltDirectory ? this._archivePrebuilt(program, archiveCallback) - : this._buildAndArchive(program, archiveCallback); -}; + : this._buildAndArchive(program, archiveCallback) +} Lambda.prototype._archivePrebuilt = function (program, archiveCallback) { - var codeDirectory = this._codeDirectory(); - var _this = this; + var codeDirectory = this._codeDirectory() + var _this = this // It is switched to `_ rsync` by environment variable. // (Used if there is a problem with `_ fileCopy`) // If there is no problem even if deleting `_rsync`, this switching process is deleted - var copyFunction = '_fileCopy'; + var copyFunction = '_fileCopy' if (process.env.NODE_LAMBDA_COPY_FUNCTION === 'rsync') { - console.log('=> INFO: Use rsync for copy'); - copyFunction = '_rsync'; + console.log('=> INFO: Use rsync for copy') + copyFunction = '_rsync' } this[copyFunction](program, program.prebuiltDirectory, codeDirectory, false, function (err) { if (err) { - return archiveCallback(err); + return archiveCallback(err) } - console.log('=> Zipping deployment package'); - _this._zip(program, codeDirectory, archiveCallback); - }); -}; + console.log('=> Zipping deployment package') + _this._zip(program, codeDirectory, archiveCallback) + }) +} Lambda.prototype._buildAndArchive = function (program, archiveCallback) { if (!fs.existsSync('.env')) { - console.warn('[Warning] `.env` file does not exist.'); - console.info('Execute `node-lambda setup` as necessary and set it up.'); + console.warn('[Warning] `.env` file does not exist.') + console.info('Execute `node-lambda setup` as necessary and set it up.') } // Warn if not building on 64-bit linux - var arch = process.platform + '.' + process.arch; + var arch = process.platform + '.' + process.arch if (arch !== 'linux.x64' && !program.dockerImage) { console.warn('Warning!!! You are building on a platform that is not 64-bit Linux (%s). ' + 'If any of your Node dependencies include C-extensions, they may not work as expected in the ' + - 'Lambda environment.\n\n', arch); + 'Lambda environment.\n\n', arch) } - var _this = this; - var codeDirectory = _this._codeDirectory(); - var lambdaSrcDirectory = program.sourceDirectory ? program.sourceDirectory.replace(/\/$/, '') : '.'; + var _this = this + var codeDirectory = _this._codeDirectory() + var lambdaSrcDirectory = program.sourceDirectory ? program.sourceDirectory.replace(/\/$/, '') : '.' _this._cleanDirectory(codeDirectory, function (err) { if (err) { - return archiveCallback(err); + return archiveCallback(err) } - console.log('=> Moving files to temporary directory'); + console.log('=> Moving files to temporary directory') // It is switched to `_ rsync` by environment variable. // (Used if there is a problem with `_ fileCopy`) // If there is no problem even if deleting `_rsync`, this switching process is deleted - var copyFunction = '_fileCopy'; + var copyFunction = '_fileCopy' if (process.env.NODE_LAMBDA_COPY_FUNCTION === 'rsync') { - console.log('=> INFO: Use rsync for copy'); - copyFunction = '_rsync'; + console.log('=> INFO: Use rsync for copy') + copyFunction = '_rsync' } // Move files to tmp folder _this[copyFunction](program, lambdaSrcDirectory, codeDirectory, true, function (err) { if (err) { - return archiveCallback(err); + return archiveCallback(err) } - console.log('=> Running npm install --production'); + console.log('=> Running npm install --production') _this._npmInstall(program, codeDirectory, function (err) { if (err) { - return archiveCallback(err); + return archiveCallback(err) } _this._postInstallScript(program, codeDirectory, function (err) { if (err) { - return archiveCallback(err); + return archiveCallback(err) } - console.log('=> Zipping deployment package'); - _this._zip(program, codeDirectory, archiveCallback); - }); - }); - }); - }); -}; + console.log('=> Zipping deployment package') + _this._zip(program, codeDirectory, archiveCallback) + }) + }) + }) + }) +} Lambda.prototype._listEventSourceMappings = function (lambda, params, cb) { return lambda.listEventSourceMappings(params, function (err, data) { - var eventSourceMappings = []; + var eventSourceMappings = [] if (!err && data && data.EventSourceMappings) { - eventSourceMappings = data.EventSourceMappings; + eventSourceMappings = data.EventSourceMappings } - return cb(err, eventSourceMappings); - }); -}; + return cb(err, eventSourceMappings) + }) +} Lambda.prototype._updateEventSources = function (lambda, functionName, existingEventSourceList, eventSourceList, cb) { if (eventSourceList == null) { - return cb(null, []); + return cb(null, []) } - var updateEventSourceList = []; + var updateEventSourceList = [] // Checking new and update event sources for (let i in eventSourceList) { - let isExisting = false; + let isExisting = false for (let j in existingEventSourceList) { if (eventSourceList[i]['EventSourceArn'] === existingEventSourceList[j]['EventSourceArn']) { - isExisting = true; + isExisting = true updateEventSourceList.push({ 'type': 'update', 'FunctionName': functionName, 'Enabled': eventSourceList[i]['Enabled'], 'BatchSize': eventSourceList[i]['BatchSize'], 'UUID': existingEventSourceList[j]['UUID'] - }); - break; + }) + break } } @@ -566,17 +566,17 @@ Lambda.prototype._updateEventSources = function (lambda, functionName, existingE 'Enabled': eventSourceList[i]['Enabled'] ? eventSourceList[i]['Enabled'] : false, 'BatchSize': eventSourceList[i]['BatchSize'] ? eventSourceList[i]['BatchSize'] : 100, 'StartingPosition': eventSourceList[i]['StartingPosition'] ? eventSourceList[i]['StartingPosition'] : 'LATEST' - }); + }) } } // Checking delete event sources for (let i in existingEventSourceList) { - let isExisting = false; + let isExisting = false for (let j in eventSourceList) { if (eventSourceList[j]['EventSourceArn'] === existingEventSourceList[i]['EventSourceArn']) { - isExisting = true; - break; + isExisting = true + break } } @@ -585,136 +585,136 @@ Lambda.prototype._updateEventSources = function (lambda, functionName, existingE updateEventSourceList.push({ 'type': 'delete', 'UUID': existingEventSourceList[i]['UUID'] - }); + }) } } return async.map(updateEventSourceList, function (updateEventSource, _cb) { switch (updateEventSource['type']) { case 'create': - delete updateEventSource['type']; + delete updateEventSource['type'] lambda.createEventSourceMapping(updateEventSource, function (err, data) { - return _cb(err, data); - }); - break; + return _cb(err, data) + }) + break case 'update': - delete updateEventSource['type']; + delete updateEventSource['type'] lambda.updateEventSourceMapping(updateEventSource, function (err, data) { - return _cb(err, data); - }); - break; + return _cb(err, data) + }) + break case 'delete': - delete updateEventSource['type']; + delete updateEventSource['type'] lambda.deleteEventSourceMapping(updateEventSource, function (err, data) { - return _cb(err, data); - }); - break; + return _cb(err, data) + }) + break } }, function (err, results) { - return cb(err, results); - }); -}; + return cb(err, results) + }) +} Lambda.prototype._updateScheduleEvents = function (scheduleEvents, functionArn, scheduleList, cb) { if (scheduleList == null) { - return cb(null, []); + return cb(null, []) } return async.series(scheduleList.map(function (schedule) { return function (_cb) { - const params = Object.assign(schedule, { FunctionArn: functionArn }); + const params = Object.assign(schedule, { FunctionArn: functionArn }) scheduleEvents.add(params).then(function (data) { - _cb(null, params); + _cb(null, params) }).catch(function (err) { - _cb(err); - }); - }; + _cb(err) + }) + } }), function (err, results) { - cb(err, results); - }); -}; + cb(err, results) + }) +} Lambda.prototype.package = function (program) { - var _this = this; + var _this = this if (!program.packageDirectory) { - throw new Error('packageDirectory not specified!'); + throw new Error('packageDirectory not specified!') } try { - var isDir = fs.lstatSync(program.packageDirectory).isDirectory(); + var isDir = fs.lstatSync(program.packageDirectory).isDirectory() if (!isDir) { - throw new Error(program.packageDirectory + ' is not a directory!'); + throw new Error(program.packageDirectory + ' is not a directory!') } } catch (err) { if (err.code === 'ENOENT') { - console.log('=> Creating package directory'); - fs.mkdirsSync(program.packageDirectory); + console.log('=> Creating package directory') + fs.mkdirsSync(program.packageDirectory) } else { - throw err; + throw err } } _this._archive(program, function (err, buffer) { if (err) { - throw err; + throw err } - var basename = program.functionName + (program.environment ? '-' + program.environment : ''); - var zipfile = path.join(program.packageDirectory, basename + '.zip'); - console.log('=> Writing packaged zip'); + var basename = program.functionName + (program.environment ? '-' + program.environment : '') + var zipfile = path.join(program.packageDirectory, basename + '.zip') + console.log('=> Writing packaged zip') fs.writeFile(zipfile, buffer, function (err) { if (err) { - throw err; + throw err } - console.log('Packaged zip created: ' + zipfile); - }); - }); -}; + console.log('Packaged zip created: ' + zipfile) + }) + }) +} Lambda.prototype.deploy = function (program) { - var _this = this; - var regions = program.region.split(','); + var _this = this + var regions = program.region.split(',') _this._archive(program, function (err, buffer) { if (err) { - throw err; + throw err } - console.log('=> Reading zip file to memory'); - var params = _this._params(program, buffer); + console.log('=> Reading zip file to memory') + var params = _this._params(program, buffer) - console.log('=> Reading event source file to memory'); - var eventSourceList = _this._eventSourceList(program); + console.log('=> Reading event source file to memory') + var eventSourceList = _this._eventSourceList(program) async.map(regions, function (region, cb) { - console.log('=> Uploading zip file to AWS Lambda ' + region + ' with parameters:'); - console.log(params); + console.log('=> Uploading zip file to AWS Lambda ' + region + ' with parameters:') + console.log(params) var awsSecurity = { region: region - }; + } if (program.profile) { aws.config.credentials = new aws.SharedIniFileCredentials({ profile: program.profile - }); + }) } else { - awsSecurity.accessKeyId = program.accessKey; - awsSecurity.secretAccessKey = program.secretKey; + awsSecurity.accessKeyId = program.accessKey + awsSecurity.secretAccessKey = program.secretKey } if (program.sessionToken) { - awsSecurity.sessionToken = program.sessionToken; + awsSecurity.sessionToken = program.sessionToken } if (program.deployTimeout) { - aws.config.httpOptions.timeout = parseInt(program.deployTimeout); + aws.config.httpOptions.timeout = parseInt(program.deployTimeout) } - aws.config.update(awsSecurity); + aws.config.update(awsSecurity) var lambda = new aws.Lambda({ apiVersion: '2015-03-31' - }); - var scheduleEvents = new ScheduleEvents(aws); + }) + var scheduleEvents = new ScheduleEvents(aws) // Checking function return lambda.getFunction({ @@ -724,27 +724,27 @@ Lambda.prototype.deploy = function (program) { // Function does not exist return _this._uploadNew(lambda, params, function (err, results) { if (err) { - throw err; + throw err } - console.log('=> Zip file(s) done uploading. Results follow: '); - console.log(results); + console.log('=> Zip file(s) done uploading. Results follow: ') + console.log(results) async.parallel([ function (_callback) { // Updating event source(s) _this._updateEventSources(lambda, params.FunctionName, [], eventSourceList.EventSourceMappings, function (err, results) { - _callback(err, results); - }); + _callback(err, results) + }) }, function (_callback) { _this._updateScheduleEvents(scheduleEvents, results.FunctionArn, eventSourceList.ScheduleEvents, function (err, results) { - _callback(err, results); - }); + _callback(err, results) + }) } ], function (err, results) { - cb(err, results); - }); - }); + cb(err, results) + }) + }) } // Function exists @@ -752,46 +752,46 @@ Lambda.prototype.deploy = function (program) { 'FunctionName': params.FunctionName }, function (err, existingEventSourceList) { if (err) { - throw err; + throw err } return async.parallel([ function (_callback) { _this._uploadExisting(lambda, params, function (err, results) { if (err) { - throw err; + throw err } - console.log('=> Zip file(s) done uploading. Results follow: '); - console.log(results); + console.log('=> Zip file(s) done uploading. Results follow: ') + console.log(results) _this._updateScheduleEvents(scheduleEvents, results.FunctionArn, eventSourceList.ScheduleEvents, function (err, results) { - _callback(err, results); - }); - }); + _callback(err, results) + }) + }) }, function (_callback) { _this._updateEventSources(lambda, params.FunctionName, existingEventSourceList, eventSourceList.EventSourceMappings, function (err, results) { - _callback(err, results); - }); + _callback(err, results) + }) } ], function (err, results) { - cb(err, results); - }); - }); - }); + cb(err, results) + }) + }) + }) }, function (err, results) { if (err) { - throw err; + throw err } const resultsIsEmpty = results.filter(function (result) { return result.filter(function (res) { - return res.length > 0; - }).length > 0; - }).length === 0; + return res.length > 0 + }).length > 0 + }).length === 0 if (!resultsIsEmpty) { - console.log('=> All tasks done. Results follow: '); - console.log(JSON.stringify(results, null, ' ')); + console.log('=> All tasks done. Results follow: ') + console.log(JSON.stringify(results, null, ' ')) } - }); - }); -}; + }) + }) +} -module.exports = new Lambda(); +module.exports = new Lambda() diff --git a/lib/schedule_events.js b/lib/schedule_events.js index d4646745..25b4ae2e 100644 --- a/lib/schedule_events.js +++ b/lib/schedule_events.js @@ -1,26 +1,26 @@ -'use strict'; +'use strict' const ScheduleEvents = function (aws) { // Authenticated `aws` object in `lib/main.js` this.lambda = new aws.Lambda({ apiVersion: '2015-03-31' - }); + }) this.cloudwatchevents = new aws.CloudWatchEvents({ apiVersion: '2015-10-07' - }); -}; + }) +} ScheduleEvents.prototype = { _ruleDescription: (params) => { if ('ScheduleDescription' in params && params.ScheduleDescription != null) { - return `${params.ScheduleDescription}`; + return `${params.ScheduleDescription}` } else { - return `${params.ScheduleName} - ${params.ScheduleExpression}`; + return `${params.ScheduleName} - ${params.ScheduleExpression}` } }, _functionName: (params) => { - return params.FunctionArn.split(':').pop(); + return params.FunctionArn.split(':').pop() }, _putRulePrams: function (params) { @@ -29,19 +29,19 @@ ScheduleEvents.prototype = { Description: this._ruleDescription(params), State: params.ScheduleState, ScheduleExpression: params.ScheduleExpression - }; + } }, _putRule: function (params) { - const _this = this; + const _this = this // return RuleArn if created return new Promise((resolve) => { - const _params = _this._putRulePrams(params); + const _params = _this._putRulePrams(params) _this.cloudwatchevents.putRule(_params, (err, rule) => { - if (err) throw err; - resolve(rule); - }); - }); + if (err) throw err + resolve(rule) + }) + }) }, _addPermissionParams: function (params) { @@ -51,22 +51,22 @@ ScheduleEvents.prototype = { Principal: 'events.amazonaws.com', SourceArn: params.RuleArn, StatementId: params.ScheduleName - }; + } }, _addPermission: function (params) { - const _this = this; + const _this = this return new Promise((resolve) => { - const _params = _this._addPermissionParams(params); + const _params = _this._addPermissionParams(params) _this.lambda.addPermission(_params, (err, data) => { if (err) { - if (err.code !== 'ResourceConflictException') throw err; + if (err.code !== 'ResourceConflictException') throw err // If it exists it will result in an error but there is no problem. - resolve('Already exists permission'); + resolve('Already exists permission') } - resolve(data); - }); - }); + resolve(data) + }) + }) }, _putTargetsParams: function (params) { @@ -76,31 +76,31 @@ ScheduleEvents.prototype = { Arn: params.FunctionArn, Id: this._functionName(params) }] - }; + } }, _putTargets: function (params) { - const _this = this; + const _this = this return new Promise((resolve) => { - const _params = _this._putTargetsParams(params); + const _params = _this._putTargetsParams(params) _this.cloudwatchevents.putTargets(_params, (err, data) => { // even if it is already registered, it will not be an error. - if (err) throw (err); - resolve(data); - }); - }); + if (err) throw (err) + resolve(data) + }) + }) }, add: function (params) { - const _this = this; + const _this = this return Promise.resolve().then(() => { - return _this._putRule(params); + return _this._putRule(params) }).then((rule) => { - return _this._addPermission(Object.assign(params, rule)); + return _this._addPermission(Object.assign(params, rule)) }).then((data) => { - return _this._putTargets(params); - }); + return _this._putTargets(params) + }) } -}; +} -module.exports = ScheduleEvents; +module.exports = ScheduleEvents diff --git a/test/handler/index.js b/test/handler/index.js index 40a5ec96..3f7036ef 100644 --- a/test/handler/index.js +++ b/test/handler/index.js @@ -1,14 +1,14 @@ -'use strict'; +'use strict' exports.handler = (event, context, callback) => { // It changes to a boolean value with `!!` context.callbackWaitsForEmptyEventLoop = - !!event.callbackWaitsForEmptyEventLoop; + !!event.callbackWaitsForEmptyEventLoop if (event.asyncTest) { - setTimeout(() => console.log('sleep 3500 msec'), 3500); + setTimeout(() => console.log('sleep 3500 msec'), 3500) } /* eslint-disable no-eval */ - eval(event.callbackCode); -}; + eval(event.callbackCode) +} diff --git a/test/main.js b/test/main.js index 603a2386..9d2ae9e5 100644 --- a/test/main.js +++ b/test/main.js @@ -1,15 +1,15 @@ -'use strict'; +'use strict' -var path = require('path'); -var os = require('os'); -var chai = require('chai'); -var program = require('commander'); -var fs = require('fs-extra'); -var Hoek = require('hoek'); -var lambda = require(path.join(__dirname, '..', 'lib', 'main')); -var Zip = require('node-zip'); +var path = require('path') +var os = require('os') +var chai = require('chai') +var program = require('commander') +var fs = require('fs-extra') +var Hoek = require('hoek') +var lambda = require(path.join(__dirname, '..', 'lib', 'main')) +var Zip = require('node-zip') -var assert = chai.assert; +var assert = chai.assert var originalProgram = { environment: 'development', @@ -31,16 +31,16 @@ var originalProgram = { contextFile: 'context.json', deployTimeout: 120000, prebuiltDirectory: '' -}; +} -var codeDirectory = lambda._codeDirectory(); +var codeDirectory = lambda._codeDirectory() function _timeout (params) { // Even if timeout is set for the whole test for Windows, // if it is set in local it will be valid. // For Windows, do not set it with local. if (process.platform !== 'win32') { - params.this.timeout(params.sec * 1000); + params.this.timeout(params.sec * 1000) } } @@ -49,187 +49,187 @@ describe('lib/main', function () { if (process.platform === 'win32') { // It seems that it takes time for file operation in Windows. // So set `timeout(60000)` for the whole test. - this.timeout(60000); + this.timeout(60000) } beforeEach(function () { - program = Hoek.clone(originalProgram); - }); + program = Hoek.clone(originalProgram) + }) it('version should be set', function () { - assert.equal(lambda.version, '0.10.0'); - }); + assert.equal(lambda.version, '0.10.0') + }) describe('_codeDirectory', function () { it('.lambda in the current directory', function () { - assert.equal(lambda._codeDirectory(), path.resolve('.', '.lambda')); - }); - }); + assert.equal(lambda._codeDirectory(), path.resolve('.', '.lambda')) + }) + }) describe('_params', function () { // http://docs.aws.amazon.com/lambda/latest/dg/API_CreateFunction.html#SSS-CreateFunction-request-FunctionName const functionNamePattern = - /(arn:aws:lambda:)?([a-z]{2}-[a-z]+-\d{1}:)?(\d{12}:)?(function:)?([a-zA-Z0-9-_]+)(:(\$LATEST|[a-zA-Z0-9-_]+))?/; + /(arn:aws:lambda:)?([a-z]{2}-[a-z]+-\d{1}:)?(\d{12}:)?(function:)?([a-zA-Z0-9-_]+)(:(\$LATEST|[a-zA-Z0-9-_]+))?/ it('appends environment to original functionName', function () { - var params = lambda._params(program); - assert.equal(params.FunctionName, '___node-lambda-development'); - assert.match(params.FunctionName, functionNamePattern); - }); + var params = lambda._params(program) + assert.equal(params.FunctionName, '___node-lambda-development') + assert.match(params.FunctionName, functionNamePattern) + }) it('appends environment to original functionName (production)', function () { - program.environment = 'production'; - var params = lambda._params(program); - assert.equal(params.FunctionName, '___node-lambda-production'); - assert.match(params.FunctionName, functionNamePattern); - }); + program.environment = 'production' + var params = lambda._params(program) + assert.equal(params.FunctionName, '___node-lambda-production') + assert.match(params.FunctionName, functionNamePattern) + }) it('appends version to original functionName', function () { - program.lambdaVersion = '2015-02-01'; - var params = lambda._params(program); - assert.equal(params.FunctionName, '___node-lambda-development-2015-02-01'); - assert.match(params.FunctionName, functionNamePattern); - }); + program.lambdaVersion = '2015-02-01' + var params = lambda._params(program) + assert.equal(params.FunctionName, '___node-lambda-development-2015-02-01') + assert.match(params.FunctionName, functionNamePattern) + }) it('appends version to original functionName (value not allowed by AWS)', function () { - program.lambdaVersion = '2015.02.01'; - var params = lambda._params(program); - assert.equal(params.FunctionName, '___node-lambda-development-2015_02_01'); - assert.match(params.FunctionName, functionNamePattern); - }); + program.lambdaVersion = '2015.02.01' + var params = lambda._params(program) + assert.equal(params.FunctionName, '___node-lambda-development-2015_02_01') + assert.match(params.FunctionName, functionNamePattern) + }) it('appends VpcConfig to params when vpc params set', function () { - program.vpcSubnets = 'subnet-00000000,subnet-00000001,subnet-00000002'; - program.vpcSecurityGroups = 'sg-00000000,sg-00000001,sg-00000002'; - var params = lambda._params(program); - assert.equal(params.VpcConfig.SubnetIds[0], program.vpcSubnets.split(',')[0]); - assert.equal(params.VpcConfig.SubnetIds[1], program.vpcSubnets.split(',')[1]); - assert.equal(params.VpcConfig.SubnetIds[2], program.vpcSubnets.split(',')[2]); - assert.equal(params.VpcConfig.SecurityGroupIds[0], program.vpcSecurityGroups.split(',')[0]); - assert.equal(params.VpcConfig.SecurityGroupIds[1], program.vpcSecurityGroups.split(',')[1]); - assert.equal(params.VpcConfig.SecurityGroupIds[2], program.vpcSecurityGroups.split(',')[2]); - }); + program.vpcSubnets = 'subnet-00000000,subnet-00000001,subnet-00000002' + program.vpcSecurityGroups = 'sg-00000000,sg-00000001,sg-00000002' + var params = lambda._params(program) + assert.equal(params.VpcConfig.SubnetIds[0], program.vpcSubnets.split(',')[0]) + assert.equal(params.VpcConfig.SubnetIds[1], program.vpcSubnets.split(',')[1]) + assert.equal(params.VpcConfig.SubnetIds[2], program.vpcSubnets.split(',')[2]) + assert.equal(params.VpcConfig.SecurityGroupIds[0], program.vpcSecurityGroups.split(',')[0]) + assert.equal(params.VpcConfig.SecurityGroupIds[1], program.vpcSecurityGroups.split(',')[1]) + assert.equal(params.VpcConfig.SecurityGroupIds[2], program.vpcSecurityGroups.split(',')[2]) + }) it('does not append VpcConfig when params are not set', function () { - var params = lambda._params(program); - assert.equal(Object.keys(params.VpcConfig.SubnetIds).length, 0); - assert.equal(Object.keys(params.VpcConfig.SecurityGroupIds).length, 0); - }); + var params = lambda._params(program) + assert.equal(Object.keys(params.VpcConfig.SubnetIds).length, 0) + assert.equal(Object.keys(params.VpcConfig.SecurityGroupIds).length, 0) + }) it('appends DeadLetterConfig to params when DLQ params set', function () { ['', 'arn:aws:sqs:test'].forEach(function (v) { - program.deadLetterConfigTargetArn = v; - const params = lambda._params(program); - assert.equal(params.DeadLetterConfig.TargetArn, v, v); - }); - }); + program.deadLetterConfigTargetArn = v + const params = lambda._params(program) + assert.equal(params.DeadLetterConfig.TargetArn, v, v) + }) + }) it('does not append DeadLetterConfig when params are not set', function () { - delete program.deadLetterConfigTargetArn; - var params = lambda._params(program); - assert.isNull(params.DeadLetterConfig.TargetArn); - }); + delete program.deadLetterConfigTargetArn + var params = lambda._params(program) + assert.isNull(params.DeadLetterConfig.TargetArn) + }) it('appends TracingConfig to params when params set', function () { - program.tracingConfig = 'Active'; - const params = lambda._params(program); - assert.equal(params.TracingConfig.Mode, 'Active'); - }); + program.tracingConfig = 'Active' + const params = lambda._params(program) + assert.equal(params.TracingConfig.Mode, 'Active') + }) it('does not append TracingConfig when params are not set', function () { - program.tracingConfig = ''; - const params = lambda._params(program); - assert.isNull(params.TracingConfig.Mode); - }); + program.tracingConfig = '' + const params = lambda._params(program) + assert.isNull(params.TracingConfig.Mode) + }) describe('configFile', function () { beforeEach(function () { // Prep... - fs.writeFileSync('tmp.env', 'FOO=bar\nBAZ=bing\n'); - fs.writeFileSync('empty.env', ''); - }); + fs.writeFileSync('tmp.env', 'FOO=bar\nBAZ=bing\n') + fs.writeFileSync('empty.env', '') + }) afterEach(function () { - fs.unlinkSync('tmp.env'); - fs.unlinkSync('empty.env'); - }); + fs.unlinkSync('tmp.env') + fs.unlinkSync('empty.env') + }) it('adds variables when configFile param is set', function () { - program.configFile = 'tmp.env'; - var params = lambda._params(program); - assert.equal(params.Environment.Variables['FOO'], 'bar'); - assert.equal(params.Environment.Variables['BAZ'], 'bing'); - }); + program.configFile = 'tmp.env' + var params = lambda._params(program) + assert.equal(params.Environment.Variables['FOO'], 'bar') + assert.equal(params.Environment.Variables['BAZ'], 'bing') + }) it('when configFile param is set but it is an empty file', function () { - program.configFile = 'empty.env'; - var params = lambda._params(program); - assert.equal(Object.keys(params.Environment.Variables).length, 0); - }); + program.configFile = 'empty.env' + var params = lambda._params(program) + assert.equal(Object.keys(params.Environment.Variables).length, 0) + }) it('does not add when configFile param is not set', function () { - var params = lambda._params(program); - assert.isNull(params.Environment.Variables); - }); - }); - }); + var params = lambda._params(program) + assert.isNull(params.Environment.Variables) + }) + }) + }) describe('_cleanDirectory', function () { it('`codeDirectory` is empty', function (done) { lambda._cleanDirectory(codeDirectory, function () { - assert.isTrue(fs.existsSync(codeDirectory)); - const contents = fs.readdirSync(codeDirectory); - assert.equal(contents.length, 0); - done(); - }); - }); + assert.isTrue(fs.existsSync(codeDirectory)) + const contents = fs.readdirSync(codeDirectory) + assert.equal(contents.length, 0) + done() + }) + }) it('`codeDirectory` is empty. (For `codeDirectory` where the file was present)', function (done) { lambda._fileCopy(program, '.', codeDirectory, true, function (err, result) { - assert.isNull(err); - const contents = fs.readdirSync(codeDirectory); - assert.isTrue(contents.length > 0); + assert.isNull(err) + const contents = fs.readdirSync(codeDirectory) + assert.isTrue(contents.length > 0) lambda._cleanDirectory(codeDirectory, function () { - assert.isTrue(fs.existsSync(codeDirectory)); - const contents = fs.readdirSync(codeDirectory); - assert.equal(contents.length, 0); - done(); - }); - }); - }); - }); + assert.isTrue(fs.existsSync(codeDirectory)) + const contents = fs.readdirSync(codeDirectory) + assert.equal(contents.length, 0) + done() + }) + }) + }) + }) function rsyncTests (funcName) { before(function () { - fs.mkdirSync('build'); - fs.mkdirsSync(path.join('__unittest', 'hoge')); - fs.mkdirsSync(path.join('__unittest', 'fuga')); - fs.writeFileSync(path.join('__unittest', 'hoge', 'piyo')); - fs.writeFileSync(path.join('__unittest', 'hoge', 'package.json')); - fs.writeFileSync('fuga'); - }); + fs.mkdirSync('build') + fs.mkdirsSync(path.join('__unittest', 'hoge')) + fs.mkdirsSync(path.join('__unittest', 'fuga')) + fs.writeFileSync(path.join('__unittest', 'hoge', 'piyo')) + fs.writeFileSync(path.join('__unittest', 'hoge', 'package.json')) + fs.writeFileSync('fuga') + }) after(function () { ['build', 'fuga', '__unittest'].forEach(function (path) { - fs.removeSync(path); - }); - }); + fs.removeSync(path) + }) + }) beforeEach(function (done) { - lambda._cleanDirectory(codeDirectory, done); - }); + lambda._cleanDirectory(codeDirectory, done) + }) it(funcName + ' an index.js as well as other files', function (done) { lambda[funcName](program, '.', codeDirectory, true, function (err, result) { - assert.isNull(err); + assert.isNull(err) var contents = fs.readdirSync(codeDirectory); ['index.js', 'package.json'].forEach(function (needle) { - assert.include(contents, needle, `Target: "${needle}"`); + assert.include(contents, needle, `Target: "${needle}"`) }); ['node_modules', 'build'].forEach(function (needle) { - assert.notInclude(contents, needle, `Target: "${needle}"`); - }); - done(); - }); - }); + assert.notInclude(contents, needle, `Target: "${needle}"`) + }) + done() + }) + }) describe('when there are excluded files', function () { beforeEach(function (done) { @@ -241,363 +241,363 @@ describe('lib/main', function () { '*main*', path.join('__unittest', 'hoge', '*'), path.join('fuga', path.sep) - ].join(' '); - done(); - }); + ].join(' ') + done() + }) it(funcName + ' an index.js as well as other files', function (done) { lambda[funcName](program, '.', codeDirectory, true, function (err, result) { - assert.isNull(err); + assert.isNull(err) var contents = fs.readdirSync(codeDirectory); ['index.js', 'package.json'].forEach(function (needle) { - assert.include(contents, needle, `Target: "${needle}"`); - }); - done(); - }); - }); + assert.include(contents, needle, `Target: "${needle}"`) + }) + done() + }) + }) it(funcName + ' excludes files matching excludeGlobs', function (done) { lambda[funcName](program, '.', codeDirectory, true, function (err, result) { - assert.isNull(err); + assert.isNull(err) var contents = fs.readdirSync(codeDirectory); ['__unittest', 'fuga'].forEach(function (needle) { - assert.include(contents, needle, `Target: "${needle}"`); + assert.include(contents, needle, `Target: "${needle}"`) }); ['node-lambda.png', 'test'].forEach(function (needle) { - assert.notInclude(contents, needle, `Target: "${needle}"`); - }); + assert.notInclude(contents, needle, `Target: "${needle}"`) + }) - contents = fs.readdirSync(path.join(codeDirectory, 'lib')); - assert.notInclude(contents, 'main.js', 'Target: "lib/main.js"'); + contents = fs.readdirSync(path.join(codeDirectory, 'lib')) + assert.notInclude(contents, 'main.js', 'Target: "lib/main.js"') - contents = fs.readdirSync(path.join(codeDirectory, '__unittest')); - assert.include(contents, 'hoge', 'Target: "__unittest/hoge"'); - assert.notInclude(contents, 'fuga', 'Target: "__unittest/fuga"'); + contents = fs.readdirSync(path.join(codeDirectory, '__unittest')) + assert.include(contents, 'hoge', 'Target: "__unittest/hoge"') + assert.notInclude(contents, 'fuga', 'Target: "__unittest/fuga"') - contents = fs.readdirSync(path.join(codeDirectory, '__unittest', 'hoge')); - assert.equal(contents.length, 0, 'directory:__unittest/hoge is empty'); - done(); - }); - }); + contents = fs.readdirSync(path.join(codeDirectory, '__unittest', 'hoge')) + assert.equal(contents.length, 0, 'directory:__unittest/hoge is empty') + done() + }) + }) it(funcName + ' should not exclude package.json, even when excluded by excludeGlobs', function (done) { - program.excludeGlobs = '*.json'; + program.excludeGlobs = '*.json' lambda[funcName](program, '.', codeDirectory, true, function (err, result) { - assert.isNull(err); - var contents = fs.readdirSync(codeDirectory); - assert.include(contents, 'package.json'); - done(); - }); - }); + assert.isNull(err) + var contents = fs.readdirSync(codeDirectory) + assert.include(contents, 'package.json') + done() + }) + }) it(funcName + ' should not include package.json when --prebuiltDirectory is set', function (done) { - var buildDir = '.build_' + Date.now(); + var buildDir = '.build_' + Date.now() after(function () { - fs.removeSync(buildDir); - }); + fs.removeSync(buildDir) + }) - fs.mkdirSync(buildDir); - fs.writeFileSync(path.join(buildDir, 'testa')); - fs.writeFileSync(path.join(buildDir, 'package.json')); + fs.mkdirSync(buildDir) + fs.writeFileSync(path.join(buildDir, 'testa')) + fs.writeFileSync(path.join(buildDir, 'package.json')) - program.excludeGlobs = '*.json'; - program.prebuiltDirectory = buildDir; + program.excludeGlobs = '*.json' + program.prebuiltDirectory = buildDir lambda[funcName](program, buildDir, codeDirectory, true, function (err, result) { - assert.isNull(err); - var contents = fs.readdirSync(codeDirectory); - assert.notInclude(contents, 'package.json', 'Target: "packages.json"'); - assert.include(contents, 'testa', 'Target: "testa"'); - done(); - }); - }); - }); + assert.isNull(err) + var contents = fs.readdirSync(codeDirectory) + assert.notInclude(contents, 'package.json', 'Target: "packages.json"') + assert.include(contents, 'testa', 'Target: "testa"') + done() + }) + }) + }) } - describe('_fileCopy', function () { rsyncTests('_fileCopy'); }); + describe('_fileCopy', function () { rsyncTests('_fileCopy') }) if (process.platform === 'win32') { - it('For Windows, `_rsync` tests pending'); + it('For Windows, `_rsync` tests pending') } else { - describe('_rsync', function () { rsyncTests('_rsync'); }); + describe('_rsync', function () { rsyncTests('_rsync') }) } describe('_npmInstall', function () { beforeEach(function (done) { lambda._cleanDirectory(codeDirectory, function (err) { if (err) { - return done(err); + return done(err) } lambda._fileCopy(program, '.', codeDirectory, true, function (err) { if (err) { - return done(err); + return done(err) } - done(); - }); - }); - }); + done() + }) + }) + }) it('_npm adds node_modules', function (done) { - _timeout({ this: this, sec: 30 }); // give it time to build the node modules + _timeout({ this: this, sec: 30 }) // give it time to build the node modules lambda._npmInstall(program, codeDirectory, function (err, result) { - assert.isNull(err); - var contents = fs.readdirSync(codeDirectory); - assert.include(contents, 'node_modules'); - done(); - }); - }); - }); + assert.isNull(err) + var contents = fs.readdirSync(codeDirectory) + assert.include(contents, 'node_modules') + done() + }) + }) + }) describe('_postInstallScript', function () { if (process.platform === 'win32') { - return it('`_postInstallScript` test does not support Windows.'); + return it('`_postInstallScript` test does not support Windows.') } - const postInstallScriptPath = path.join(codeDirectory, 'post_install.sh'); - var hook; + const postInstallScriptPath = path.join(codeDirectory, 'post_install.sh') + var hook /** * Capture console output */ function captureStream (stream) { - var oldWrite = stream.write; - var buf = ''; + var oldWrite = stream.write + var buf = '' stream.write = function (chunk, encoding, callback) { - buf += chunk.toString(); // chunk is a String or Buffer - oldWrite.apply(stream, arguments); + buf += chunk.toString() // chunk is a String or Buffer + oldWrite.apply(stream, arguments) } return { unhook: function unhook () { - stream.write = oldWrite; + stream.write = oldWrite }, captured: function () { - return buf; + return buf } - }; + } } beforeEach(function () { - hook = captureStream(process.stdout); - }); + hook = captureStream(process.stdout) + }) afterEach(function () { - hook.unhook(); + hook.unhook() if (fs.existsSync(postInstallScriptPath)) { - fs.unlinkSync(postInstallScriptPath); + fs.unlinkSync(postInstallScriptPath) } - }); + }) it('should not throw any errors if no script', function (done) { lambda._postInstallScript(program, codeDirectory, function (err) { - assert.isNull(err); - done(); - }); - }); + assert.isNull(err) + done() + }) + }) it('should throw any errors if script fails', function (done) { - fs.writeFileSync(postInstallScriptPath, '___fails___'); + fs.writeFileSync(postInstallScriptPath, '___fails___') lambda._postInstallScript(program, codeDirectory, function (err) { - assert.instanceOf(err, Error); - assert.match(err.message, /^Error: Command failed:/); - done(); - }); - }); + assert.instanceOf(err, Error) + assert.match(err.message, /^Error: Command failed:/) + done() + }) + }) it('running script gives expected output', function (done) { - fs.writeFileSync(postInstallScriptPath, fs.readFileSync(path.join('test', 'post_install.sh'))); - fs.chmodSync(path.join(codeDirectory, 'post_install.sh'), '755'); + fs.writeFileSync(postInstallScriptPath, fs.readFileSync(path.join('test', 'post_install.sh'))) + fs.chmodSync(path.join(codeDirectory, 'post_install.sh'), '755') lambda._postInstallScript(program, codeDirectory, function (err) { - assert.isNull(err); + assert.isNull(err) assert.equal( `=> Running post install script post_install.sh\n\t\tYour environment is ${program.environment}\n`, hook.captured() - ); - done(); - }); - }); - }); + ) + done() + }) + }) + }) describe('_zip', function () { beforeEach(function (done) { - _timeout({ this: this, sec: 30 }); // give it time to build the node modules + _timeout({ this: this, sec: 30 }) // give it time to build the node modules lambda._cleanDirectory(codeDirectory, function (err) { if (err) { - return done(err); + return done(err) } lambda._fileCopy(program, '.', codeDirectory, true, function (err) { if (err) { - return done(err); + return done(err) } lambda._npmInstall(program, codeDirectory, function (err) { if (err) { - return done(err); + return done(err) } - done(); - }); - }); - }); - }); + done() + }) + }) + }) + }) it('zips the file and has an index.js file', function (done) { - _timeout({ this: this, sec: 30 }); // give it time to zip + _timeout({ this: this, sec: 30 }) // give it time to zip lambda._zip(program, codeDirectory, function (err, data) { - assert.isNull(err); - var archive = new Zip(data); + assert.isNull(err) + var archive = new Zip(data) var contents = Object.keys(archive.files).map(function (k) { - return archive.files[k].name.toString(); - }); - assert.include(contents, 'index.js'); - done(); - }); - }); - }); + return archive.files[k].name.toString() + }) + assert.include(contents, 'index.js') + done() + }) + }) + }) describe('_archive', function () { it('installs and zips with an index.js file and node_modules/async', function (done) { - _timeout({ this: this, sec: 30 }); // give it time to zip + _timeout({ this: this, sec: 30 }) // give it time to zip lambda._archive(program, function (err, data) { - assert.isNull(err); - var archive = new Zip(data); + assert.isNull(err) + var archive = new Zip(data) var contents = Object.keys(archive.files).map(function (k) { - return archive.files[k].name.toString(); - }); - assert.include(contents, 'index.js'); - assert.include(contents, path.join('node_modules', 'async', 'lib', 'async.js')); - done(); - }); - }); + return archive.files[k].name.toString() + }) + assert.include(contents, 'index.js') + assert.include(contents, path.join('node_modules', 'async', 'lib', 'async.js')) + done() + }) + }) it('packages a prebuilt module without installing', function (done) { - _timeout({ this: this, sec: 30 }); // give it time to zip - var buildDir = '.build_' + Date.now(); + _timeout({ this: this, sec: 30 }) // give it time to zip + var buildDir = '.build_' + Date.now() after(function () { - fs.removeSync(buildDir); - }); + fs.removeSync(buildDir) + }) - fs.mkdirSync(buildDir); - fs.mkdirSync(path.join(buildDir, 'd')); - fs.mkdirSync(path.join(buildDir, 'node_modules')); - fs.writeFileSync(path.join(buildDir, 'node_modules', 'a'), '...'); - fs.writeFileSync(path.join(buildDir, 'testa'), '...'); - fs.writeFileSync(path.join(buildDir, 'd', 'testb'), '...'); + fs.mkdirSync(buildDir) + fs.mkdirSync(path.join(buildDir, 'd')) + fs.mkdirSync(path.join(buildDir, 'node_modules')) + fs.writeFileSync(path.join(buildDir, 'node_modules', 'a'), '...') + fs.writeFileSync(path.join(buildDir, 'testa'), '...') + fs.writeFileSync(path.join(buildDir, 'd', 'testb'), '...') - program.prebuiltDirectory = buildDir; + program.prebuiltDirectory = buildDir lambda._archive(program, function (err, data) { - assert.isNull(err); - var archive = new Zip(data); + assert.isNull(err) + var archive = new Zip(data) var contents = Object.keys(archive.files).map(function (k) { - return archive.files[k].name.toString(); + return archive.files[k].name.toString() }); [ 'testa', path.join('d', 'testb'), path.join('node_modules', 'a') ].forEach(function (needle) { - assert.include(contents, needle, `Target: "${needle}"`); - }); - done(); - }); - }); - }); + assert.include(contents, needle, `Target: "${needle}"`) + }) + done() + }) + }) + }) describe('_readArchive', function () { - const testZipFile = path.join(os.tmpdir(), 'node-lambda-test.zip'); - var bufferExpected = null; + const testZipFile = path.join(os.tmpdir(), 'node-lambda-test.zip') + var bufferExpected = null before(function (done) { - _timeout({ this: this, sec: 30 }); // give it time to zip + _timeout({ this: this, sec: 30 }) // give it time to zip lambda._zip(program, codeDirectory, function (err, data) { - assert.isNull(err); - bufferExpected = data; - fs.writeFileSync(testZipFile, data); - done(); - }); - }); + assert.isNull(err) + bufferExpected = data + fs.writeFileSync(testZipFile, data) + done() + }) + }) after(function () { - fs.unlinkSync(testZipFile); - }); + fs.unlinkSync(testZipFile) + }) it('_readArchive fails (undefined)', function (done) { lambda._readArchive(program, function (err, data) { - assert.isUndefined(data); - assert.instanceOf(err, Error); - assert.equal(err.message, 'No such Zipfile [undefined]'); - done(); - }); - }); + assert.isUndefined(data) + assert.instanceOf(err, Error) + assert.equal(err.message, 'No such Zipfile [undefined]') + done() + }) + }) it('_readArchive fails (does not exists file)', function (done) { - const filePath = path.join(path.resolve('/aaaa'), 'bbbb'); - const _program = Object.assign({ deployZipfile: filePath }, program); + const filePath = path.join(path.resolve('/aaaa'), 'bbbb') + const _program = Object.assign({ deployZipfile: filePath }, program) lambda._readArchive(_program, function (err, data) { - assert.isUndefined(data); - assert.instanceOf(err, Error); - assert.equal(err.message, `No such Zipfile [${filePath}]`); - done(); - }); - }); + assert.isUndefined(data) + assert.instanceOf(err, Error) + assert.equal(err.message, `No such Zipfile [${filePath}]`) + done() + }) + }) it('_readArchive reads the contents of the zipfile', function (done) { - const _program = Object.assign({ deployZipfile: testZipFile }, program); + const _program = Object.assign({ deployZipfile: testZipFile }, program) lambda._readArchive(_program, function (err, data) { - assert.isNull(err); - assert.deepEqual(data, bufferExpected); - done(); - }); - }); + assert.isNull(err) + assert.deepEqual(data, bufferExpected) + done() + }) + }) describe('If value is set in `deployZipfile`, _readArchive is executed in _archive', function () { it('`deployZipfile` is a invalid value. Process from creation of zip file', function (done) { - const filePath = path.join(path.resolve('/aaaa'), 'bbbb'); - const _program = Object.assign({ deployZipfile: filePath }, program); - _timeout({ this: this, sec: 30 }); // give it time to zip + const filePath = path.join(path.resolve('/aaaa'), 'bbbb') + const _program = Object.assign({ deployZipfile: filePath }, program) + _timeout({ this: this, sec: 30 }) // give it time to zip lambda._archive(_program, function (err, data) { - assert.isNull(err); + assert.isNull(err) // same test as "installs and zips with an index.js file and node_modules/async" - var archive = new Zip(data); + var archive = new Zip(data) var contents = Object.keys(archive.files).map(function (k) { - return archive.files[k].name.toString(); - }); - assert.include(contents, 'index.js'); - assert.include(contents, path.join('node_modules', 'async', 'lib', 'async.js')); - done(); - }); - }); + return archive.files[k].name.toString() + }) + assert.include(contents, 'index.js') + assert.include(contents, path.join('node_modules', 'async', 'lib', 'async.js')) + done() + }) + }) it('`deployZipfile` is a valid value._archive reads the contents of the zipfile', function (done) { - const _program = Object.assign({ deployZipfile: testZipFile }, program); + const _program = Object.assign({ deployZipfile: testZipFile }, program) lambda._archive(_program, function (err, data) { - assert.isNull(err); - assert.deepEqual(data, bufferExpected); - done(); - }); - }); - }); - }); + assert.isNull(err) + assert.deepEqual(data, bufferExpected) + done() + }) + }) + }) + }) describe('environment variable injection at runtime', function () { beforeEach(function () { // Prep... - fs.writeFileSync('tmp.env', 'FOO=bar\nBAZ=bing\n'); - }); + fs.writeFileSync('tmp.env', 'FOO=bar\nBAZ=bing\n') + }) afterEach(function () { - fs.unlinkSync('tmp.env'); - }); + fs.unlinkSync('tmp.env') + }) it('should inject environment variables at runtime', function () { // Run it... lambda._setRunTimeEnvironmentVars({ configFile: 'tmp.env' - }, process.cwd()); + }, process.cwd()) - assert.equal(process.env.FOO, 'bar'); - assert.equal(process.env.BAZ, 'bing'); - }); - }); + assert.equal(process.env.FOO, 'bar') + assert.equal(process.env.BAZ, 'bing') + }) + }) describe('create sample files', function () { const targetFiles = [ @@ -606,84 +606,84 @@ describe('lib/main', function () { 'event.json', 'deploy.env', 'event_sources.json' - ]; + ] after(function () { targetFiles.forEach(function (file) { - fs.unlinkSync(file); - }); - program.eventSourceFile = ''; - }); + fs.unlinkSync(file) + }) + program.eventSourceFile = '' + }) it('should create sample files', function () { - lambda.setup(program); + lambda.setup(program) - const libPath = path.join(__dirname, '..', 'lib'); + const libPath = path.join(__dirname, '..', 'lib') targetFiles.forEach(function (targetFile) { - const boilerplateFile = path.join(libPath, `${targetFile}.example`); + const boilerplateFile = path.join(libPath, `${targetFile}.example`) assert.equal( fs.readFileSync(targetFile).toString(), fs.readFileSync(boilerplateFile).toString(), targetFile - ); - }); - }); + ) + }) + }) describe('_eventSourceList', function () { it('program.eventSourceFile is empty value', function () { - program.eventSourceFile = ''; + program.eventSourceFile = '' assert.deepEqual( lambda._eventSourceList(program), { EventSourceMappings: null, ScheduleEvents: null } - ); - }); + ) + }) it('program.eventSourceFile is invalid value', function () { - const dirPath = path.join(path.resolve('/hoge'), 'fuga'); - program.eventSourceFile = dirPath; + const dirPath = path.join(path.resolve('/hoge'), 'fuga') + program.eventSourceFile = dirPath assert.throws( - () => { lambda._eventSourceList(program); }, + () => { lambda._eventSourceList(program) }, Error, `ENOENT: no such file or directory, open '${dirPath}'` - ); - }); + ) + }) describe('program.eventSourceFile is valid value', function () { before(function () { fs.writeFileSync('only_EventSourceMappings.json', JSON.stringify({ EventSourceMappings: [{ test: 1 }] - })); + })) fs.writeFileSync('only_ScheduleEvents.json', JSON.stringify({ ScheduleEvents: [{ test: 2 }] - })); - }); + })) + }) after(function () { - fs.unlinkSync('only_EventSourceMappings.json'); - fs.unlinkSync('only_ScheduleEvents.json'); - }); + fs.unlinkSync('only_EventSourceMappings.json') + fs.unlinkSync('only_ScheduleEvents.json') + }) it('only EventSourceMappings', function () { - program.eventSourceFile = 'only_EventSourceMappings.json'; + program.eventSourceFile = 'only_EventSourceMappings.json' const expected = { EventSourceMappings: [{ test: 1 }], ScheduleEvents: [] - }; - assert.deepEqual(lambda._eventSourceList(program), expected); - }); + } + assert.deepEqual(lambda._eventSourceList(program), expected) + }) it('only ScheduleEvents', function () { - program.eventSourceFile = 'only_ScheduleEvents.json'; + program.eventSourceFile = 'only_ScheduleEvents.json' const expected = { EventSourceMappings: [], ScheduleEvents: [{ test: 2 }] - }; - assert.deepEqual(lambda._eventSourceList(program), expected); - }); + } + assert.deepEqual(lambda._eventSourceList(program), expected) + }) it('EventSourceMappings & ScheduleEvents', function () { - program.eventSourceFile = 'event_sources.json'; + program.eventSourceFile = 'event_sources.json' const expected = { EventSourceMappings: [{ BatchSize: 100, @@ -696,10 +696,10 @@ describe('lib/main', function () { ScheduleState: 'ENABLED', ScheduleExpression: 'rate(1 hour)' }] - }; - assert.deepEqual(lambda._eventSourceList(program), expected); - }); - }); + } + assert.deepEqual(lambda._eventSourceList(program), expected) + }) + }) describe('old style event_sources.json', function () { const oldStyleValue = [{ @@ -707,47 +707,47 @@ describe('lib/main', function () { Enabled: true, EventSourceArn: 'your event source arn', StartingPosition: 'LATEST' - }]; - const fileName = 'event_sources_old_style.json'; + }] + const fileName = 'event_sources_old_style.json' before(function () { - fs.writeFileSync(fileName, JSON.stringify(oldStyleValue)); - }); + fs.writeFileSync(fileName, JSON.stringify(oldStyleValue)) + }) after(function () { - fs.unlinkSync(fileName); - }); + fs.unlinkSync(fileName) + }) it('program.eventSourceFile is valid value', function () { - program.eventSourceFile = fileName; + program.eventSourceFile = fileName const expected = { EventSourceMappings: oldStyleValue, ScheduleEvents: [] - }; - assert.deepEqual(lambda._eventSourceList(program), expected); - }); - }); - }); - }); + } + assert.deepEqual(lambda._eventSourceList(program), expected) + }) + }) + }) + }) describe('_updateEventSources', function () { it('program.eventSourceFile is empty value', function () { - program.eventSourceFile = ''; - const eventSourceList = lambda._eventSourceList(program); + program.eventSourceFile = '' + const eventSourceList = lambda._eventSourceList(program) return new Promise(function (resolve) { lambda._updateEventSources(lambda, '', [], eventSourceList.EventSourceMappings, function (err, results) { - resolve({ err: err, results: results }); - }); + resolve({ err: err, results: results }) + }) }).then(function (actual) { - const expected = { err: null, results: [] }; - assert.deepEqual(actual, expected); - }); - }); - }); + const expected = { err: null, results: [] } + assert.deepEqual(actual, expected) + }) + }) + }) describe('_updateScheduleEvents', function () { - const aws = require('aws-sdk-mock'); - const ScheduleEvents = require(path.join('..', 'lib', 'schedule_events')); + const aws = require('aws-sdk-mock') + const ScheduleEvents = require(path.join('..', 'lib', 'schedule_events')) const eventSourcesJsonValue = { ScheduleEvents: [{ ScheduleName: 'node-lambda-test-schedule', @@ -755,56 +755,56 @@ describe('lib/main', function () { ScheduleExpression: 'rate(1 hour)', ScheduleDescription: 'Run node-lambda-test-function once per hour' }] - }; + } - var schedule = null; + var schedule = null before(function () { aws.mock('CloudWatchEvents', 'putRule', function (params, callback) { - callback(null, {}); - }); + callback(null, {}) + }) aws.mock('CloudWatchEvents', 'putTargets', function (params, callback) { - callback(null, {}); - }); + callback(null, {}) + }) aws.mock('Lambda', 'addPermission', function (params, callback) { - callback(null, {}); - }); + callback(null, {}) + }) fs.writeFileSync( 'event_sources.json', JSON.stringify(eventSourcesJsonValue) - ); + ) - schedule = new ScheduleEvents(require('aws-sdk')); - }); + schedule = new ScheduleEvents(require('aws-sdk')) + }) after(function () { - fs.unlinkSync('event_sources.json'); - aws.restore('CloudWatchEvents'); - aws.restore('Lambda'); - }); + fs.unlinkSync('event_sources.json') + aws.restore('CloudWatchEvents') + aws.restore('Lambda') + }) it('program.eventSourceFile is empty value', function () { - program.eventSourceFile = ''; - const eventSourceList = lambda._eventSourceList(program); + program.eventSourceFile = '' + const eventSourceList = lambda._eventSourceList(program) return new Promise(function (resolve) { lambda._updateScheduleEvents(schedule, '', eventSourceList.ScheduleEvents, function (err, results) { - resolve({ err: err, results: results }); - }); + resolve({ err: err, results: results }) + }) }).then(function (actual) { - const expected = { err: null, results: [] }; - assert.deepEqual(actual, expected); - }); - }); + const expected = { err: null, results: [] } + assert.deepEqual(actual, expected) + }) + }) it('simple test with mock', function () { - program.eventSourceFile = 'event_sources.json'; - const eventSourceList = lambda._eventSourceList(program); - const functionArn = 'arn:aws:lambda:us-west-2:XXX:function:node-lambda-test-function'; + program.eventSourceFile = 'event_sources.json' + const eventSourceList = lambda._eventSourceList(program) + const functionArn = 'arn:aws:lambda:us-west-2:XXX:function:node-lambda-test-function' return new Promise(function (resolve) { lambda._updateScheduleEvents(schedule, functionArn, eventSourceList.ScheduleEvents, function (err, results) { - resolve({ err: err, results: results }); - }); + resolve({ err: err, results: results }) + }) }).then(function (actual) { const expected = { err: undefined, @@ -812,51 +812,51 @@ describe('lib/main', function () { eventSourcesJsonValue.ScheduleEvents[0], { FunctionArn: functionArn } )] - }; - assert.deepEqual(actual, expected); - }); - }); - }); + } + assert.deepEqual(actual, expected) + }) + }) + }) describe('check env vars before create sample files', function () { const filesCreatedBySetup = [ '.env', 'deploy.env', 'event_sources.json' - ]; + ] beforeEach(function () { - fs.writeFileSync('newContext.json', '{"FOO"="bar"\n"BAZ"="bing"\n}'); - fs.writeFileSync('newEvent.json', '{"FOO"="bar"}'); - }); + fs.writeFileSync('newContext.json', '{"FOO"="bar"\n"BAZ"="bing"\n}') + fs.writeFileSync('newEvent.json', '{"FOO"="bar"}') + }) afterEach(function () { - fs.unlinkSync('newContext.json'); - fs.unlinkSync('newEvent.json'); + fs.unlinkSync('newContext.json') + fs.unlinkSync('newEvent.json') filesCreatedBySetup.forEach(function (file) { - fs.unlinkSync(file); - }); - }); + fs.unlinkSync(file) + }) + }) it('should use existing sample files', function () { - program.eventFile = 'newEvent.json'; - program.contextFile = 'newContext.json'; + program.eventFile = 'newEvent.json' + program.contextFile = 'newContext.json' - lambda.setup(program); + lambda.setup(program) - assert.equal(fs.readFileSync('newContext.json').toString(), '{"FOO"="bar"\n"BAZ"="bing"\n}'); - assert.equal(fs.readFileSync('newEvent.json').toString(), '{"FOO"="bar"}'); + assert.equal(fs.readFileSync('newContext.json').toString(), '{"FOO"="bar"\n"BAZ"="bing"\n}') + assert.equal(fs.readFileSync('newEvent.json').toString(), '{"FOO"="bar"}') - const libPath = path.join(__dirname, '..', 'lib'); + const libPath = path.join(__dirname, '..', 'lib') filesCreatedBySetup.forEach(function (targetFile) { - const boilerplateFile = path.join(libPath, `${targetFile}.example`); + const boilerplateFile = path.join(libPath, `${targetFile}.example`) assert.equal( fs.readFileSync(targetFile).toString(), fs.readFileSync(boilerplateFile).toString(), targetFile - ); - }); - }); - }); -}); + ) + }) + }) + }) +}) diff --git a/test/node-lambda.js b/test/node-lambda.js index 9c194847..1800b407 100644 --- a/test/node-lambda.js +++ b/test/node-lambda.js @@ -1,11 +1,11 @@ -'use strict'; +'use strict' -const assert = require('chai').assert; -const path = require('path'); -const fs = require('fs-extra'); -const spawn = require('child_process').spawn; -const execSync = require('child_process').execSync; -const nodeLambdaPath = path.join(__dirname, '..', 'bin', 'node-lambda'); +const assert = require('chai').assert +const path = require('path') +const fs = require('fs-extra') +const spawn = require('child_process').spawn +const execSync = require('child_process').execSync +const nodeLambdaPath = path.join(__dirname, '..', 'bin', 'node-lambda') /* global before, after, describe, it */ // The reason for specifying the node command in this test is to support Windows. @@ -16,27 +16,27 @@ describe('bin/node-lambda', () => { nodeLambdaPath, 'run', '--handler', '__test.handler', '--eventFile', 'event.json' - ]); - var stdoutString = ''; + ]) + var stdoutString = '' run.stdout.on('data', (data) => { - stdoutString += data.toString().replace(/\r|\n/g, ''); - }); + stdoutString += data.toString().replace(/\r|\n/g, '') + }) run.on('exit', (code) => { - assert.match(stdoutString, expectedValues.stdoutRegExp); - assert.equal(code, expectedValues.exitCode); - done(); - }); - }; + assert.match(stdoutString, expectedValues.stdoutRegExp) + assert.equal(code, expectedValues.exitCode) + done() + }) + } const _generateEventFile = (eventObj) => { - fs.writeFileSync('event.json', JSON.stringify(eventObj)); - }; + fs.writeFileSync('event.json', JSON.stringify(eventObj)) + } before(() => { - execSync(`node ${nodeLambdaPath} setup`); - fs.copy(path.join(__dirname, 'handler', 'index.js'), '__test.js'); - }); + execSync(`node ${nodeLambdaPath} setup`) + fs.copy(path.join(__dirname, 'handler', 'index.js'), '__test.js') + }) after(() => { [ @@ -46,95 +46,95 @@ describe('bin/node-lambda', () => { 'deploy.env', 'event_sources.json', '__test.js' - ].forEach((file) => fs.unlinkSync(file)); - }); + ].forEach((file) => fs.unlinkSync(file)) + }) describe('node-lambda run (Handler only sync processing)', () => { const eventObj = { asyncTest: false, callbackWaitsForEmptyEventLoop: true // True is the default value of Lambda - }; + } it('`node-lambda run` exitCode is `0` (callback(null))', (done) => { _generateEventFile(Object.assign(eventObj, { callbackCode: 'callback(null);' - })); - _testMain({ stdoutRegExp: /Success:$/, exitCode: 0 }, done); - }); + })) + _testMain({ stdoutRegExp: /Success:$/, exitCode: 0 }, done) + }) it('`node-lambda run` exitCode is `0` (callback(null, "text"))', (done) => { _generateEventFile(Object.assign(eventObj, { callbackCode: 'callback(null, "text");' - })); - _testMain({ stdoutRegExp: /Success:"text"$/, exitCode: 0 }, done); - }); + })) + _testMain({ stdoutRegExp: /Success:"text"$/, exitCode: 0 }, done) + }) it('`node-lambda run` exitCode is `255` (callback(new Error("e")))', (done) => { _generateEventFile(Object.assign(eventObj, { callbackCode: 'callback(new Error("e"));' - })); - _testMain({ stdoutRegExp: /Error: Error: e$/, exitCode: 255 }, done); - }); - }); + })) + _testMain({ stdoutRegExp: /Error: Error: e$/, exitCode: 255 }, done) + }) + }) describe('node-lambda run (Handler includes async processing)', () => { describe('callbackWaitsForEmptyEventLoop = true', function () { - this.timeout(5000); // give it time to setTimeout + this.timeout(5000) // give it time to setTimeout const eventObj = { asyncTest: true, callbackWaitsForEmptyEventLoop: true - }; + } it('`node-lambda run` exitCode is `0` (callback(null))', (done) => { _generateEventFile(Object.assign(eventObj, { callbackCode: 'callback(null);' - })); - _testMain({ stdoutRegExp: /Success:sleep 3500 msec$/, exitCode: 0 }, done); - }); + })) + _testMain({ stdoutRegExp: /Success:sleep 3500 msec$/, exitCode: 0 }, done) + }) it('`node-lambda run` exitCode is `0` (callback(null, "text"))', (done) => { _generateEventFile(Object.assign(eventObj, { callbackCode: 'callback(null, "text");' - })); - _testMain({ stdoutRegExp: /Success:"text"sleep 3500 msec$/, exitCode: 0 }, done); - }); + })) + _testMain({ stdoutRegExp: /Success:"text"sleep 3500 msec$/, exitCode: 0 }, done) + }) it('`node-lambda run` exitCode is `255` (callback(new Error("e")))', (done) => { _generateEventFile(Object.assign(eventObj, { callbackCode: 'callback(new Error("e"));' - })); - _testMain({ stdoutRegExp: /Error: Error: esleep 3500 msec$/, exitCode: 255 }, done); - }); - }); + })) + _testMain({ stdoutRegExp: /Error: Error: esleep 3500 msec$/, exitCode: 255 }, done) + }) + }) describe('callbackWaitsForEmptyEventLoop = false', () => { const eventObj = { asyncTest: true, callbackWaitsForEmptyEventLoop: false - }; + } it('`node-lambda run` exitCode is `0` (callback(null))', (done) => { _generateEventFile(Object.assign(eventObj, { callbackCode: 'callback(null);' - })); - _testMain({ stdoutRegExp: /Success:$/, exitCode: 0 }, done); - }); + })) + _testMain({ stdoutRegExp: /Success:$/, exitCode: 0 }, done) + }) it('`node-lambda run` exitCode is `0` (callback(null, "text"))', (done) => { _generateEventFile(Object.assign(eventObj, { callbackCode: 'callback(null, "text");' - })); - _testMain({ stdoutRegExp: /Success:"text"$/, exitCode: 0 }, done); - }); + })) + _testMain({ stdoutRegExp: /Success:"text"$/, exitCode: 0 }, done) + }) it('`node-lambda run` exitCode is `255` (callback(new Error("e")))', (done) => { _generateEventFile(Object.assign(eventObj, { callbackCode: 'callback(new Error("e"));' - })); - _testMain({ stdoutRegExp: /Error: Error: e$/, exitCode: 255 }, done); - }); - }); - }); - }); -}); + })) + _testMain({ stdoutRegExp: /Error: Error: e$/, exitCode: 255 }, done) + }) + }) + }) + }) +}) diff --git a/test/schedule_events.js b/test/schedule_events.js index 1058dbf7..d917852a 100644 --- a/test/schedule_events.js +++ b/test/schedule_events.js @@ -1,10 +1,10 @@ -'use strict'; +'use strict' -const assert = require('chai').assert; -const path = require('path'); -const aws = require('aws-sdk-mock'); -aws.setSDK(path.resolve('node_modules/aws-sdk')); -const ScheduleEvents = require(path.join('..', 'lib', 'schedule_events')); +const assert = require('chai').assert +const path = require('path') +const aws = require('aws-sdk-mock') +aws.setSDK(path.resolve('node_modules/aws-sdk')) +const ScheduleEvents = require(path.join('..', 'lib', 'schedule_events')) const params = { FunctionArn: 'arn:aws:lambda:us-west-2:XXX:function:node-lambda-test-function', @@ -12,7 +12,7 @@ const params = { ScheduleState: 'ENABLED', ScheduleExpression: 'rate(1 hour)', ScheduleDescription: null -}; +} const mockResponse = { putRule: { @@ -34,60 +34,60 @@ const mockResponse = { FailedEntries: [], FailedEntryCount: 0 } -}; +} -var schedule = null; +var schedule = null /* global before, after, describe, it */ describe('lib/schedule_events', () => { before(() => { aws.mock('CloudWatchEvents', 'putRule', (params, callback) => { - callback(null, mockResponse.putRule); - }); + callback(null, mockResponse.putRule) + }) aws.mock('CloudWatchEvents', 'putTargets', (params, callback) => { - callback(null, mockResponse.putTargets); - }); + callback(null, mockResponse.putTargets) + }) aws.mock('Lambda', 'addPermission', (params, callback) => { - callback(null, mockResponse.addPermission); - }); + callback(null, mockResponse.addPermission) + }) - schedule = new ScheduleEvents(require('aws-sdk')); - }); + schedule = new ScheduleEvents(require('aws-sdk')) + }) describe('_ruleDescription (default)', () => { it('correct value', () => { assert.equal( schedule._ruleDescription(params), 'node-lambda-test-schedule - rate(1 hour)' - ); - }); - }); + ) + }) + }) describe('_ruleDescription (custom)', () => { before(() => { - params.ScheduleDescription = 'Run node-lambda-test-function once per hour'; - }); + params.ScheduleDescription = 'Run node-lambda-test-function once per hour' + }) after(() => { - params.ScheduleDescription = null; - }); + params.ScheduleDescription = null + }) it('correct value', () => { assert.equal( schedule._ruleDescription(params), 'Run node-lambda-test-function once per hour' - ); - }); - }); + ) + }) + }) describe('_functionName', () => { it('correct value', () => { assert.equal( schedule._functionName(params), 'node-lambda-test-function' - ); - }); - }); + ) + }) + }) describe('_putRulePrams', () => { it('correct value', () => { @@ -96,10 +96,10 @@ describe('lib/schedule_events', () => { Description: 'node-lambda-test-schedule - rate(1 hour)', State: 'ENABLED', ScheduleExpression: 'rate(1 hour)' - }; - assert.deepEqual(schedule._putRulePrams(params), expected); - }); - }); + } + assert.deepEqual(schedule._putRulePrams(params), expected) + }) + }) describe('_addPermissionParams', () => { it('correct value', () => { @@ -109,11 +109,11 @@ describe('lib/schedule_events', () => { Principal: 'events.amazonaws.com', SourceArn: 'arn:aws:events:hoge:fuga', StatementId: 'node-lambda-test-schedule' - }; - const _params = Object.assign(params, mockResponse.putRule); - assert.deepEqual(schedule._addPermissionParams(_params), expected); - }); - }); + } + const _params = Object.assign(params, mockResponse.putRule) + assert.deepEqual(schedule._addPermissionParams(_params), expected) + }) + }) describe('_putTargetsParams', () => { it('correct value', () => { @@ -123,41 +123,41 @@ describe('lib/schedule_events', () => { Arn: 'arn:aws:lambda:us-west-2:XXX:function:node-lambda-test-function', Id: 'node-lambda-test-function' }] - }; - assert.deepEqual(schedule._putTargetsParams(params), expected); - }); - }); + } + assert.deepEqual(schedule._putTargetsParams(params), expected) + }) + }) describe('_putRule', () => { it('using mock', () => { return schedule._putRule(params).then((data) => { - assert.deepEqual(data, mockResponse.putRule); - }); - }); - }); + assert.deepEqual(data, mockResponse.putRule) + }) + }) + }) describe('_addPermission', () => { it('using mock', () => { - const _params = Object.assign(params, mockResponse.putTargets); + const _params = Object.assign(params, mockResponse.putTargets) return schedule._addPermission(_params).then((data) => { - assert.deepEqual(data, mockResponse.addPermission); - }); - }); - }); + assert.deepEqual(data, mockResponse.addPermission) + }) + }) + }) describe('_putTargets', () => { it('using mock', () => { return schedule._putTargets(params).then((data) => { - assert.deepEqual(data, mockResponse.putTargets); - }); - }); - }); + assert.deepEqual(data, mockResponse.putTargets) + }) + }) + }) describe('add', () => { it('using mock', () => { return schedule.add(params).then((data) => { - assert.deepEqual(data, mockResponse.putTargets); - }); - }); - }); -}); + assert.deepEqual(data, mockResponse.putTargets) + }) + }) + }) +})