jaws-framework
Version:
JAWS is the serverless framework powered by Amazon Web Services.
374 lines (302 loc) • 10.1 kB
JavaScript
/**
* JAWS Command: dash
*/
var JawsError = require('../jaws-error'),
JawsCli = require('../utils/cli'),
Promise = require('bluebird'),
fs = require('fs'),
os = require('os'),
path = require('path'),
chalk = require('chalk'),
utils = require('../utils/index'),
CMDtag = require('./tag'),
CMDdeployLambda = require('./deploy_lambda'),
CMDdeployEndpoint = require('./deploy_endpoint');
/**
* Run
* @param JAWS
* @param stage
* @param region
* @param allTagged
* @returns {Promise}
*/
module.exports.run = function(JAWS, stage, region, allTagged) {
var command = new CMD(JAWS, stage, region, allTagged);
return command.run();
};
/**
* CMD Class
* @param JAWS
* @param stage
* @param region
* @param allTagged
* @constructor
*/
function CMD(JAWS, stage, region, allTagged) {
this._JAWS = JAWS;
this._allTagged = allTagged || false;
this._stage = stage || null;
this._regions = region ? [region] : [];
this._choices = [];
}
/**
* CMD: Run
*/
CMD.prototype.run = Promise.method(function() {
var _this = this;
_this._report = {
selectedLambdas: 0,
selectedEndpoints: 0,
};
return _this._JAWS.validateProject()
.bind(_this)
.then(function() {
// If !allTagged, Show Dashboard
if (!_this._allTagged) {
return Promise.try(function() {
})
.bind(_this)
.then(_this._prepareResources)
.then(_this._prepareSummary)
.then(_this._renderDash)
.then(function(selectedResources) {
_this._resources = selectedResources;
if (!_this._resources.length) {
return false;
}
return _this._choices;
})
.each(function(resource) {
var toggled = (!!resource.toggled || false);
if (resource.type === 'lambda') {
if (toggled) _this._report.selectedLambdas++;
return CMDtag.tag('lambda', resource.value, !toggled);
} else if (resource.type === 'endpoint') {
if (toggled) _this._report.selectedEndpoints++;
return CMDtag.tag('endpoint', resource.value, !toggled);
}
});
}
})
.then(_this._promptStage)
.then(_this._promptRegion)
.then(function() {
// Status
JawsCli.log(chalk.white('-------------------------------------------'));
JawsCli.log(chalk.white(' Dashboard: Deploying Lambdas...'));
JawsCli.log(chalk.white('-------------------------------------------'));
if (!_this._allTagged && !_this._report.selectedLambdas) {
return JawsCli.log(chalk.white('No selected Lambdas to deploy.'));
}
return CMDdeployLambda.run(
_this._JAWS,
_this._stage,
(_this._regions.length > 1 ? null : _this._regions[0]),
true);
})
.then(function() {
// Status
JawsCli.log(chalk.white('-------------------------------------------'));
JawsCli.log(chalk.white(' Dashboard: Deploying Endpoints...'));
JawsCli.log(chalk.white('-------------------------------------------'));
if (!_this._allTagged && !_this._report.selectedEndpoints) {
return JawsCli.log(chalk.white('No selected Endpoints to deploy.'));
}
return CMDdeployEndpoint.run(
_this._JAWS,
_this._stage,
_this._regions,
true);
})
.then(function() {
// Status
JawsCli.log(chalk.white('-------------------------------------------'));
JawsCli.log(chalk.white(' Dashboard: Deployments Completed'));
JawsCli.log(chalk.white('-------------------------------------------'));
});
});
/**
* CMD: Prepare Resources
*/
CMD.prototype._prepareResources = Promise.method(function() {
var _this = this;
return utils.findAllAwsmJsons(path.join(_this._JAWS._meta.projectRootPath, 'aws_modules'))
.then(function(jsonPaths) {
var hybrids = [];
var lambdas = [];
// Fetch and prepare json modules
for (var i = 0; i < jsonPaths.length; i++) {
// Add modules
var json = require(jsonPaths[i]);
var module = {};
// Add Lambda
if (json.lambda) {
module.lambda = {
key: ' L) ',
value: jsonPaths[i],
type: 'lambda',
label: utils.generateLambdaName(json),
};
// Create path
var paths = jsonPaths[i].split('/');
paths = paths[paths.length - 3] + '/' + paths[paths.length - 2];
module.lambda.path = chalk.grey(paths);
}
// Add Endpoint
if (json.apiGateway) {
module.endpoint = {
key: ' E) ',
value: jsonPaths[i],
type: 'endpoint',
label: '/' + json.apiGateway.cloudFormation.Path
+ ' - ' + json.apiGateway.cloudFormation.Method,
};
// Create path
var paths = jsonPaths[i].split('/');
paths = paths[paths.length - 3] + '/' + paths[paths.length - 2];
module.endpoint.path = chalk.grey(paths);
}
if (module.lambda && module.endpoint) hybrids.push(module);
if (module.lambda && !module.endpoint) lambdas.push(module);
}
// Sort hybrids by label/paths
hybrids.sort(function(a, b) {
return (a.label < b.label) ? -1 : (a.label > b.label) ? 1 : 0;
});
// Sort lambdas by label
lambdas.sort(function(a, b) {
return (a.label < b.label) ? -1 : (a.label > b.label) ? 1 : 0;
});
// Add Lambdas back in
var modules = lambdas.concat(hybrids);
// Prepare Choices
for (var i = 0; i < modules.length; i++) {
if (modules[i].lambda || modules[i].endpoint) {
_this._choices.push({
spacer: modules[i].lambda.path ? modules[i].lambda.path : modules[i].endpoint.path,
});
}
if (modules[i].lambda) {
_this._choices.push(modules[i].lambda);
}
if (modules[i].endpoint) {
_this._choices.push(modules[i].endpoint);
}
}
});
});
/**
* CMD: Prepare Summary
*/
CMD.prototype._prepareSummary = Promise.method(function() {
var _this = this;
var lambdaCount = 0;
var endpointCount = 0;
// Count Lambdas and Endpoints
for (var i = 0; i < _this._choices.length; i++) {
if (_this._choices[i].type === 'lambda') lambdaCount++;
if (_this._choices[i].type === 'endpoint') endpointCount++;
}
_this._summary = 'Dashboard for project "' + _this._JAWS._meta.projectJson.name + '"' + os.EOL
+ chalk.white.bold(' -------------------------------------------') + os.EOL
+ chalk.white(' Project Summary') + os.EOL
+ chalk.white.bold(' -------------------------------------------') + os.EOL
+ chalk.white(' Stages: ' + os.EOL);
// Add Stage Data
for (var stage in _this._JAWS._meta.projectJson.stages) {
_this._summary = _this._summary
+ chalk.white(' ' + stage + ' ');
for (var i = 0; i < _this._JAWS._meta.projectJson.stages[stage].length; i++) {
_this._summary = _this._summary
+ chalk.grey(_this._JAWS._meta.projectJson.stages[stage][i].region + ' ')
}
_this._summary = _this._summary + os.EOL;
}
_this._summary = _this._summary
+ chalk.white(' Lambdas: ' + lambdaCount) + os.EOL
+ chalk.white(' Endpoints: ' + endpointCount) + os.EOL
+ chalk.white.bold(' -------------------------------------------') + os.EOL
+ chalk.white(' Select Resources To Deploy') + os.EOL
+ chalk.white.bold(' -------------------------------------------');
});
/**
* CMD: Render Dash
*/
CMD.prototype._renderDash = Promise.method(function() {
var _this = this;
JawsCli.log(_this._summary);
return JawsCli.select(
null,
_this._choices,
true,
' Deploy Selected -->');
});
/**
* CMD: Prompt: Stage
*/
CMD.prototype._promptStage = Promise.method(function() {
var _this = this;
// If stage exists, skip
if (_this._stage) return;
var stages = Object.keys(_this._JAWS._meta.projectJson.stages);
// Check if project has stages
if (!stages.length) {
throw new JawsError('This project has no stages');
}
// If project only has 1 stage, skip prompt
if (stages.length === 1) {
_this._stage = stages[0];
return;
}
// Create Choices
var choices = [];
for (var i = 0; i < stages.length; i++) {
choices.push({
key: (i + 1) + ') ',
value: stages[i],
label: stages[i],
});
}
return JawsCli.select('Choose a stage: ', choices, false)
.then(function(results) {
_this._stage = results[0].value;
});
});
/**
* CMD: Prompt: Region
*/
CMD.prototype._promptRegion = Promise.method(function() {
var _this = this;
// If region exists, skip
if (_this._regions.length) return;
var regions = _this._JAWS._meta.projectJson.stages[_this._stage].map(function(s) {
return s.region;
});
// Check if stage has regions
if (!regions.length) {
throw new JawsError('This stage has no regions');
}
_this._regions = regions;
// If stage only has 1 region, use it and skip prompt
if (regions.length === 1) return;
// Create Choices
var choices = [];
for (var i = 0; i < _this._regions.length; i++) {
choices.push({
key: '',
value: _this._regions[i],
label: _this._regions[i],
});
}
choices.push({
key: '',
value: 'all regions',
label: 'all regions',
});
return JawsCli.select('Choose a region within this stage: ', choices, false)
.then(function(results) {
if (results[0].value !== 'all regions') {
_this._regions = [results[0].value];
}
});
});