diff --git a/lib/RuntimeNode.js b/lib/RuntimeNode.js index 87cab7e2b..ffc3d8870 100644 --- a/lib/RuntimeNode.js +++ b/lib/RuntimeNode.js @@ -1,13 +1,13 @@ 'use strict'; const SError = require('./Error'), - SCli = require('./utils/cli'), - _ = require('lodash'), - BbPromise = require('bluebird'), - chalk = require('chalk'), - context = require('./utils/context'), - path = require('path'), - fs = BbPromise.promisifyAll(require('fs')); + SCli = require('./utils/cli'), + _ = require('lodash'), + BbPromise = require('bluebird'), + chalk = require('chalk'), + context = require('./utils/context'), + path = require('path'), + fs = BbPromise.promisifyAll(require('fs')); module.exports = function(S) { @@ -34,10 +34,10 @@ module.exports = function(S) { const handlerPath = path.join(S.getServerlessPath(), 'templates', 'nodejs', 'handler.js'); return fs.readFileAsync(handlerPath) - .then(handlerJs => BbPromise.all([ - S.utils.writeFile(func.getRootPath('handler.js'), handlerJs), - S.utils.writeFile(func.getRootPath('event.json'), {}) - ])); + .then(handlerJs => BbPromise.all([ + S.utils.writeFile(func.getRootPath('handler.js'), handlerJs), + S.utils.writeFile(func.getRootPath('event.json'), {}) + ])); } /** @@ -48,73 +48,73 @@ module.exports = function(S) { run(func, stage, region) { let _this = this, - functionEvent, - functionCall; + functionEvent, + functionCall; return BbPromise.try(function () { - // Load Event - functionEvent = S.utils.readFileSync(func.getRootPath('event.json')); + // Load Event + functionEvent = S.utils.readFileSync(func.getRootPath('event.json')); - // Load Function - let handlerArr = func.handler.split('/').pop().split('.'), - functionFile = func.getRootPath(handlerArr[0] + '.js'), - functionHandler = handlerArr[1]; + // Load Function + let handlerArr = func.handler.split('/').pop().split('.'), + functionFile = func.getRootPath(handlerArr[0] + '.js'), + functionHandler = handlerArr[1]; - functionCall = require(functionFile)[functionHandler]; - }) - .then(() => _this.getEnvVars(func, stage, region)) - .then(function (envVars) { - - // Add ENV vars (from no stage/region) to environment - for (var key in envVars) { - process.env[key] = envVars[key]; - } - }) - .then(() => { - - return new BbPromise(resolve => { - - // Call Function - functionCall(functionEvent, context(func, (err, result) => { - - SCli.log(`-----------------`); - - // Show error - if (err) { - SCli.log(chalk.bold('Failed - This Error Was Returned:')); - SCli.log(err.message); - SCli.log(err.stack); - - return resolve({ - status: 'error', - response: err.message, - error: err - }); - } - - // Show success response - SCli.log(chalk.bold('Success! - This Response Was Returned:')); - SCli.log(JSON.stringify(result, null, 4)); - return resolve({ - status: 'success', - response: result - }); - })); + functionCall = require(functionFile)[functionHandler]; }) - }) - .catch((err) => { - SCli.log(`-----------------`); + .then(() => _this.getEnvVars(func, stage, region)) + .then(function (envVars) { - SCli.log(chalk.bold('Failed - This Error Was Thrown:')); - SCli.log(err.stack || err); + // Add ENV vars (from no stage/region) to environment + for (var key in envVars) { + process.env[key] = envVars[key]; + } + }) + .then(() => { - return { - status: 'error', - response: err.message, - error: err - }; - }); + return new BbPromise(resolve => { + + // Call Function + functionCall(functionEvent, context(func, (err, result) => { + + SCli.log(`-----------------`); + + // Show error + if (err) { + SCli.log(chalk.bold('Failed - This Error Was Returned:')); + SCli.log(err.message); + SCli.log(err.stack); + + return resolve({ + status: 'error', + response: err.message, + error: err + }); + } + + // Show success response + SCli.log(chalk.bold('Success! - This Response Was Returned:')); + SCli.log(JSON.stringify(result, null, 4)); + return resolve({ + status: 'success', + response: result + }); + })); + }) + }) + .catch((err) => { + SCli.log(`-----------------`); + + SCli.log(chalk.bold('Failed - This Error Was Thrown:')); + SCli.log(err.stack || err); + + return { + status: 'error', + response: err.message, + error: err + }; + }); } /** @@ -130,12 +130,14 @@ module.exports = function(S) { let pathDist; return this.createDistDir(func.name) - .then(function (distDir) { - pathDist = distDir - }) - .then(() => this.copyFunction(func, pathDist, stage, region)) - .then(() => this._addEnvVarsInline(func, pathDist, stage, region)) - .then(() => this.generatePaths(func, pathDist)); + .then(function (distDir) { + pathDist = distDir + }) + .then(() => this.copyFunction(func, pathDist, stage, region)) + .then(() => this._addEnvVarsInline(func, pathDist, stage, region)) + .then(function() { + return pathDist; + }); } /** @@ -165,14 +167,14 @@ module.exports = function(S) { _addEnvVarsInline(func, pathDist, stage, region) { return this.getEnvVars(func, stage, region) - .then(envVars => { + .then(envVars => { - const handlerArr = func.handler.split('.'), - handlerDir = path.dirname(func.handler), - handlerFile = handlerArr[0].split('/').pop(), - handlerMethod = handlerArr[1]; + const handlerArr = func.handler.split('.'), + handlerDir = path.dirname(func.handler), + handlerFile = handlerArr[0].split('/').pop(), + handlerMethod = handlerArr[1]; - const loader = ` + const loader = ` var envVars = ${JSON.stringify(envVars, null, 2)}; for (var key in envVars) { process.env[key] = envVars[key]; @@ -180,11 +182,10 @@ module.exports = function(S) { exports.handler = require("./${handlerFile}")["${handlerMethod}"]; `; - return fs.writeFileAsync(path.join(pathDist, handlerDir, '_serverless_handler.js'), loader); - }); + return fs.writeFileAsync(path.join(pathDist, handlerDir, '_serverless_handler.js'), loader); + }); } } return RuntimeNode; - }; diff --git a/lib/actions/CodeDeployLambda.js b/lib/actions/CodeDeployLambda.js index 7cf05cfce..8e764bf69 100644 --- a/lib/actions/CodeDeployLambda.js +++ b/lib/actions/CodeDeployLambda.js @@ -8,12 +8,13 @@ module.exports = function(S) { - const path = require('path'), - SUtils = S.utils, - SError = require(S.getServerlessPath('Error')), - BbPromise = require('bluebird'), - Zip = require('node-zip'), - fs = BbPromise.promisifyAll(require('fs')); + const path = require('path'), + SUtils = S.utils, + SError = require(S.getServerlessPath('Error')), + BbPromise = require('bluebird'), + Zip = require('node-zip'), + fs = require('fs'), + fse = BbPromise.promisifyAll(require('fs-extra')); class CodeDeployLambda extends S.classes.Plugin { @@ -54,23 +55,23 @@ module.exports = function(S) { // Flow return _this._validateAndPrepare() - .bind(_this) - .then(_this._compress) - .then(_this._provision) - .then(_this._alias) - .then(function() { + .bind(_this) + .then(_this._compress) + .then(_this._provision) + .then(_this._alias) + .then(function() { - /** - * Return EVT - */ + /** + * Return EVT + */ - _this.evt.data.functioName = _this.functionName; - _this.evt.data.pathCompressed = _this.pathCompressed; - _this.evt.data.functionVersion = _this.functionVersion; - _this.evt.data.functionAliasArn = _this.functionAliasArn; - return _this.evt; + _this.evt.data.functioName = _this.functionName; + _this.evt.data.pathCompressed = _this.pathCompressed; + _this.evt.data.functionVersion = _this.functionVersion; + _this.evt.data.functionAliasArn = _this.functionAliasArn; + return _this.evt; - }); + }); } /** @@ -103,34 +104,39 @@ module.exports = function(S) { _compress() { - let zip = new Zip(); + let _this = this, + zip = new Zip(); - this.evt.options.pathsPackaged.forEach(nc => { - zip.file(nc.name, fs.readFileSync(nc.path)); - }); + return fse.walk(_this.evt.options.pathDist) + .on('readable', function () { + let item; + while ((item = this.read())) { + console.log(item); + zip.file(item.name, S.utils.readFileSync(item.path)); + } + }) + .then(function () { - // Set zipfile name - this.zipName = `${this.function.getName()}_${this.evt.options.stage}_${this.evt.options.region}`; + // Set zipfile name + _this.zipName = `${_this.function.getName()}_${_this.evt.options.stage}_${_this.evt.options.region}`; - // Compress - this.zipBuffer = zip.generate({ - type: 'nodebuffer', - compression: 'DEFLATE' - }); + // Compress + _this.zipBuffer = zip.generate({ + type: 'nodebuffer', + compression: 'DEFLATE' + }); - if (this.zipBuffer.length > 52428800) { - BbPromise.reject(new SError( - 'Zip file is > the 50MB Lambda queued limit (' + this.zipBuffer.length + ' bytes)', - SError.errorCodes.ZIP_TOO_BIG) - ); - } + if (_this.zipBuffer.length > 52428800) { + BbPromise.reject(new SError( + 'Zip file is > the 50MB Lambda queued limit (' + _this.zipBuffer.length + ' bytes)', + SError.errorCodes.ZIP_TOO_BIG)); + } - // Create compressed package - this.pathCompressed = path.join(this.project.getTempPath(), this.zipName); - fs.writeFileSync(this.pathCompressed, this.zipBuffer); - SUtils.sDebug(`"${this.evt.options.stage} - ${this.evt.options.region} - ${this.functionName}": Compressed file created - ${this.pathCompressed}`); - - return BbPromise.resolve(); + // Create compressed package + _this.pathCompressed = path.join(_this.project.getTempPath(), _this.zipName); + fs.writeFileSync(_this.pathCompressed, _this.zipBuffer); + SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.functionName}": Compressed file created - ${_this.pathCompressed}`); + }); } /** @@ -148,86 +154,86 @@ module.exports = function(S) { }; return _this.aws.request('Lambda', 'getFunction', params, _this.evt.options.stage, _this.evt.options.region) - .catch(function (e) { - _this.lambda = null; - }) - .then(function (data) { - _this.lambda = data; - }) - .then(function () { + .catch(function (e) { + _this.lambda = null; + }) + .then(function (data) { + _this.lambda = data; + }) + .then(function () { - // Create or Update Lambda - if (!_this.lambda) { + // Create or Update Lambda + if (!_this.lambda) { - SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.function.functionName}": Creating Lambda function...`); + SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.function.functionName}": Creating Lambda function...`); - // Create Lambda - let params = { - Code: { - ZipFile: _this.zipBuffer - }, - FunctionName: _this.functionName, /* required */ - Handler: _this.function.getRuntime().getHandler(_this.function), /* required */ - Role: _this.functionPopulated.customRole ? _this.functionPopulated.customRole : _this.project.getVariablesObject(_this.evt.options.stage, _this.evt.options.region).iamRoleArnLambda, /* required */ - Runtime: _this.function.getRuntime().getName('aws'), /* required */ - Description: 'Serverless Lambda function for project: ' + _this.project.name, - MemorySize: _this.functionPopulated.memorySize, - Publish: true, // Required by Serverless Framework & recommended best practice by AWS - Timeout: _this.functionPopulated.timeout, - VpcConfig: { - SecurityGroupIds: _this.functionPopulated.vpc.securityGroupIds, - SubnetIds: _this.functionPopulated.vpc.subnetIds - } - }; + // Create Lambda + let params = { + Code: { + ZipFile: _this.zipBuffer + }, + FunctionName: _this.functionName, /* required */ + Handler: _this.function.getRuntime().getHandler(_this.function), /* required */ + Role: _this.functionPopulated.customRole ? _this.functionPopulated.customRole : _this.project.getVariablesObject(_this.evt.options.stage, _this.evt.options.region).iamRoleArnLambda, /* required */ + Runtime: _this.function.getRuntime().getName('aws'), /* required */ + Description: 'Serverless Lambda function for project: ' + _this.project.name, + MemorySize: _this.functionPopulated.memorySize, + Publish: true, // Required by Serverless Framework & recommended best practice by AWS + Timeout: _this.functionPopulated.timeout, + VpcConfig: { + SecurityGroupIds: _this.functionPopulated.vpc.securityGroupIds, + SubnetIds: _this.functionPopulated.vpc.subnetIds + } + }; - return _this.aws.request('Lambda', 'createFunction', params, _this.evt.options.stage, _this.evt.options.region) - .then(function (data) { - - // Save Version & Lambda - _this.functionVersion = data.Version; - _this.lambda = data; - }) - - } else { - - SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.functionName}": Updating Lambda configuration...`); - - // Update Configuration - let params = { - FunctionName: _this.lambda.Configuration.FunctionName, /* required */ - Description: 'Serverless Lambda function for project: ' + _this.project.name, - Handler: _this.function.getRuntime().getHandler(_this.function), - MemorySize: _this.functionPopulated.memorySize, - Role: _this.functionPopulated.customRole ? _this.functionPopulated.customRole : _this.project.getVariablesObject(_this.evt.options.stage, _this.evt.options.region).iamRoleArnLambda, - Timeout: _this.functionPopulated.timeout, - VpcConfig: { - SecurityGroupIds: _this.functionPopulated.vpc.securityGroupIds, - SubnetIds: _this.functionPopulated.vpc.subnetIds - } - }; - - return _this.aws.request('Lambda', 'updateFunctionConfiguration', params, _this.evt.options.stage, _this.evt.options.region) - .then(function () { - SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.functionName}": Updating Lambda function...`); - - // Update Lambda Code - let params = { - FunctionName: _this.lambda.Configuration.FunctionName, /* required */ - Publish: true, // Required by Serverless Framework & recommended by AWS - ZipFile: _this.zipBuffer - }; - - // Update Function - return _this.aws.request('Lambda', 'updateFunctionCode', params, _this.evt.options.stage, _this.evt.options.region) + return _this.aws.request('Lambda', 'createFunction', params, _this.evt.options.stage, _this.evt.options.region) .then(function (data) { // Save Version & Lambda _this.functionVersion = data.Version; _this.lambda = data; + }) + + } else { + + SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.functionName}": Updating Lambda configuration...`); + + // Update Configuration + let params = { + FunctionName: _this.lambda.Configuration.FunctionName, /* required */ + Description: 'Serverless Lambda function for project: ' + _this.project.name, + Handler: _this.function.getRuntime().getHandler(_this.function), + MemorySize: _this.functionPopulated.memorySize, + Role: _this.functionPopulated.customRole ? _this.functionPopulated.customRole : _this.project.getVariablesObject(_this.evt.options.stage, _this.evt.options.region).iamRoleArnLambda, + Timeout: _this.functionPopulated.timeout, + VpcConfig: { + SecurityGroupIds: _this.functionPopulated.vpc.securityGroupIds, + SubnetIds: _this.functionPopulated.vpc.subnetIds + } + }; + + return _this.aws.request('Lambda', 'updateFunctionConfiguration', params, _this.evt.options.stage, _this.evt.options.region) + .then(function () { + SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.functionName}": Updating Lambda function...`); + + // Update Lambda Code + let params = { + FunctionName: _this.lambda.Configuration.FunctionName, /* required */ + Publish: true, // Required by Serverless Framework & recommended by AWS + ZipFile: _this.zipBuffer + }; + + // Update Function + return _this.aws.request('Lambda', 'updateFunctionCode', params, _this.evt.options.stage, _this.evt.options.region) + .then(function (data) { + + // Save Version & Lambda + _this.functionVersion = data.Version; + _this.lambda = data; + }); }); - }); - } - }) + } + }) } /** @@ -246,55 +252,55 @@ module.exports = function(S) { }; return _this.aws.request('Lambda', 'getAlias', params, _this.evt.options.stage, _this.evt.options.region) - .then(function() { - aliasedLambda = true; - }, function(e) { - aliasedLambda = false; - }) - .then(function() { + .then(function() { + aliasedLambda = true; + }, function(e) { + aliasedLambda = false; + }) + .then(function() { - if (aliasedLambda) { + if (aliasedLambda) { - // Update Existing Alias + // Update Existing Alias - SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.functionName}": Updating Lambda Alias for version - ${_this.functionVersion}`); + SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.functionName}": Updating Lambda Alias for version - ${_this.functionVersion}`); - let params = { - FunctionName: _this.lambda.FunctionName, /* required */ - FunctionVersion: _this.functionVersion, /* required */ - Name: _this.functionAlias, /* required */ - Description: 'Project: ' - + _this.project.name - + ' Stage: ' - + _this.evt.options.stage - }; + let params = { + FunctionName: _this.lambda.FunctionName, /* required */ + FunctionVersion: _this.functionVersion, /* required */ + Name: _this.functionAlias, /* required */ + Description: 'Project: ' + + _this.project.name + + ' Stage: ' + + _this.evt.options.stage + }; - return _this.aws.request('Lambda', 'updateAlias', params, _this.evt.options.stage, _this.evt.options.region); + return _this.aws.request('Lambda', 'updateAlias', params, _this.evt.options.stage, _this.evt.options.region); - } else { + } else { - // Create New Alias + // Create New Alias - SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.functionName}": Creating New Lambda Alias for version - ${_this.functionVersion}`); + SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.functionName}": Creating New Lambda Alias for version - ${_this.functionVersion}`); - let params = { - FunctionName: _this.lambda.FunctionName, /* required */ - FunctionVersion: _this.functionVersion, /* required */ - Name: _this.functionAlias, /* required */ - Description: 'Project: ' - + _this.project.name - + ' Stage: ' - + _this.evt.options.stage - }; + let params = { + FunctionName: _this.lambda.FunctionName, /* required */ + FunctionVersion: _this.functionVersion, /* required */ + Name: _this.functionAlias, /* required */ + Description: 'Project: ' + + _this.project.name + + ' Stage: ' + + _this.evt.options.stage + }; - return _this.aws.request('Lambda', 'createAlias', params, _this.evt.options.stage, _this.evt.options.region); - } - }) - .then(function(data) { + return _this.aws.request('Lambda', 'createAlias', params, _this.evt.options.stage, _this.evt.options.region); + } + }) + .then(function(data) { - // Save Alias - _this.functionAliasArn = data.AliasArn; - }); + // Save Alias + _this.functionAliasArn = data.AliasArn; + }); } } diff --git a/lib/actions/CodePackageLambda.js b/lib/actions/CodePackageLambda.js index debe92b3e..b8b3bfae0 100644 --- a/lib/actions/CodePackageLambda.js +++ b/lib/actions/CodePackageLambda.js @@ -112,7 +112,7 @@ module.exports = function(S) { // Create pathsPackaged for each file ready to compress return this.function.getRuntime().build(this.function, this.evt.options.stage, this.evt.options.region) - .then(paths => this.pathsPackaged = paths); + .then(pathDist => this.pathDist = pathDist); } }