mirror of
https://github.com/serverless/serverless.git
synced 2026-01-25 15:07:39 +00:00
commit
f2ce300eef
86
bin/jaws
86
bin/jaws
@ -7,6 +7,7 @@ var JawsError = require('../lib/jaws-error'),
|
||||
program = require('commander'),
|
||||
utils = require('../lib/utils'),
|
||||
Promise = require('bluebird'),
|
||||
minimist = require('minimist'),
|
||||
handleExit = utils.handleExit;
|
||||
|
||||
var JAWS = new Jaws();
|
||||
@ -20,31 +21,26 @@ program
|
||||
.version(JAWS._meta.version);
|
||||
|
||||
program
|
||||
.command('new <type> [regionName] [stageName]')
|
||||
.description('Creates JAWS "project" or "region"/"stage" in existing project. Does so in cwd. ' +
|
||||
'If type is region|stage, regionName and stageName are required. If region, the stageName is the stage that will' +
|
||||
'be primed in the new region.')
|
||||
.option('-d, --dont-exe-cf', 'Dont execute CloudFormation file')
|
||||
//Things only valid for new project below:
|
||||
.option('-p, --profile <profile name>', 'AWS profile to use (as defined in ~/.aws/credentials). Only valid for new project.')
|
||||
.option('-n, --proj-name <name>', 'Project name. Only valid for new project.')
|
||||
.option('-s, --stage <stage>', 'Stage to create. all lowercase Only valid for new project.')
|
||||
.option('-r, --region <region>', 'Region lambda(s)&API(s) will be created in (Can add more later). Only valid for new project.')
|
||||
.option('-3, --s3-bucket <bucketName>', 'S3 bucket to store stage env files. Key is JAWS/envVars/<projName>/<stage>. Bucket will be created if it DNE. Only valid for new project.')
|
||||
.option('-e, --notification-email <email>', 'Email to be notified with stack alerts. Only valid for new project.')
|
||||
.action(function(type, regionName, stageName, options) {
|
||||
type = type.toLowerCase();
|
||||
.command('new <type>')
|
||||
.allowUnknownOption()
|
||||
.description('Make a new "project", "stage", "region", "lambda" or "endpoint"')
|
||||
.action(function() {
|
||||
|
||||
// Parse Args
|
||||
var args = minimist(process.argv.slice(3));
|
||||
var type = args._[0] ? args._[0].toLowerCase() : null;
|
||||
|
||||
if (type == 'project') {
|
||||
var theCmd = require('../lib/commands/new_project');
|
||||
handleExit(theCmd.create(
|
||||
options.projName, // name is reserved in commander...
|
||||
options.stage ? options.stage.toLowerCase() : null,
|
||||
options.s3Bucket,
|
||||
options.region,
|
||||
options.notificationEmail,
|
||||
options.profile,
|
||||
options.dontExeCf
|
||||
|
||||
var CmdNewProject = require('../lib/commands/new_project');
|
||||
handleExit(CmdNewProject.run(
|
||||
args.name,
|
||||
args.stage ? args.stage.toLowerCase() : null,
|
||||
args.s3Bucket,
|
||||
args.region,
|
||||
args.email,
|
||||
args.profile,
|
||||
args.noCf
|
||||
));
|
||||
} else if (type == 'region' || type == 'stage') {
|
||||
var theCmd = require('../lib/commands/new_region_stage'),
|
||||
@ -66,7 +62,7 @@ program
|
||||
.description('Create boilerplate structure for a new lambda or api gateway (or both)')
|
||||
.option('-l, --lambda', 'will create the files needed for a lambda')
|
||||
.option('-r, --lambda-runtime', 'only nodejs supported')
|
||||
.option('-a, --api', 'will create the files needed for an api gateway configuration')
|
||||
.option('-a, --endpoint', 'will create the files needed for an api gateway configuration')
|
||||
.option('-b, --both', 'shorthand for -l -a')
|
||||
.option('-f, --function-name', 'lambda functionName. Will ensure this is unique across your project.')
|
||||
.option('-m, --resource-name', 'parent directory the functionName dir will be created in')
|
||||
@ -76,13 +72,13 @@ program
|
||||
options.lambda = true;
|
||||
}
|
||||
|
||||
if (options.api || options.both) {
|
||||
options.api = true;
|
||||
if (options.endpoint || options.both) {
|
||||
options.endpoint = true;
|
||||
}
|
||||
|
||||
var theCmd = require('../lib/commands/generate');
|
||||
handleExit(theCmd.run(
|
||||
JAWS, options.lambda, options.api, options.functionName, options.resourceName, options.lambdaRuntime
|
||||
JAWS, options.lambda, options.endpoint, options.functionName, options.resourceName, options.lambdaRuntime
|
||||
));
|
||||
});
|
||||
|
||||
@ -97,19 +93,19 @@ program
|
||||
|
||||
program
|
||||
.command('tag [type]')
|
||||
.description('Tag lambda function or api gateway resource (api) for deployment ' +
|
||||
.description('Tag lambda function or api gateway resource (endpoint) for deployment ' +
|
||||
'the next time deploy command is run. Type "lambda" is the default.')
|
||||
.option('-u, --untag', 'un-tag lambda|api')
|
||||
.option('-u, --untag', 'un-tag lambda|endpoint')
|
||||
.option('-m, --multi', 'interactively select multiple')
|
||||
.option('-a, --tag-all', 'tag all lambda|api functions in project')
|
||||
.option('-l, --list-all', 'list all tagged lambda|api functions in project')
|
||||
.option('-n, --untag-all', 'un-tag all lambda|api functions in project')
|
||||
.option('-a, --tag-all', 'tag all lambda|endpoint functions in project')
|
||||
.option('-l, --list-all', 'list all tagged lambda|endpoint functions in project')
|
||||
.option('-n, --untag-all', 'un-tag all lambda|endpoint functions in project')
|
||||
.action(function(type, options) {
|
||||
type = type || 'lambda';
|
||||
type = type.toLowerCase();
|
||||
|
||||
if (-1 == ['api', 'lambda'].indexOf(type)) {
|
||||
console.error('Unsupported type ' + type + '. Must be api|lambda');
|
||||
if (-1 == ['endpoint', 'lambda'].indexOf(type)) {
|
||||
console.error('Unsupported type ' + type + '. Must be endpoint|lambda');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@ -129,8 +125,8 @@ program
|
||||
});
|
||||
|
||||
program
|
||||
.command('deploy <type> <stage> [region]')
|
||||
.description('Deploy a lambda function (type lambda), a REST API (api), or provision AWS resources (resources) for the specified stage.' +
|
||||
.command('deploy <type> [stage] [region]')
|
||||
.description('Deploy a lambda function (type lambda), a REST API (endpoint), or provision AWS resources (resources) for the specified stage.' +
|
||||
' By default will tag and deploy type at cwd')
|
||||
.option('-t, --tags', 'Deploy all lambdas tagged as deployable in their jaws.json. Default is to just deploy cwd')
|
||||
.option('-e, --all-at-once', 'By default, lambdas are deployed once at a time. This deploys all concurrently')
|
||||
@ -138,19 +134,19 @@ program
|
||||
|
||||
type = type.toLowerCase();
|
||||
switch (type) {
|
||||
case 'api':
|
||||
case 'endpoint':
|
||||
var allTagged = (options.tags) ? true : false;
|
||||
var theCmd = require('../lib/commands/deploy_api');
|
||||
handleExit(theCmd.deployApi(JAWS, stage, region, allTagged));
|
||||
var theCmd = require('../lib/commands/deploy_endpoint');
|
||||
handleExit(theCmd.run(JAWS, stage, region, allTagged));
|
||||
break;
|
||||
case 'lambda':
|
||||
var allTagged = (options.tags) ? true : false,
|
||||
allAtOnce = (options.allAtOnce) ? true : false;
|
||||
var theCmd = require('../lib/commands/deploy_lambda');
|
||||
handleExit(theCmd.deployLambdas(JAWS, stage, allTagged, allAtOnce, region));
|
||||
handleExit(theCmd.run(JAWS, stage, region, allTagged, allAtOnce));
|
||||
break;
|
||||
default:
|
||||
console.error('Unsupported type ' + type + '. Must be api|lambda|resources');
|
||||
console.error('Unsupported type ' + type + '. Must be endpoint|lambda|resources');
|
||||
process.exit(1);
|
||||
break;
|
||||
}
|
||||
@ -204,6 +200,14 @@ program
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('dash')
|
||||
.description('Check deployment status and deploy resources for a stage and region')
|
||||
.action(function() {
|
||||
var theCmd = require('../lib/commands/dash');
|
||||
handleExit(theCmd.run(JAWS));
|
||||
});
|
||||
|
||||
program
|
||||
.command('logs <stage>')
|
||||
.description('Get logs for the lambda function in the specified stage in your current working directory.')
|
||||
|
||||
368
lib/commands/dash.js
Normal file
368
lib/commands/dash.js
Normal file
@ -0,0 +1,368 @@
|
||||
/**
|
||||
* 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 regions
|
||||
* @param allTagged
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
module.exports.run = function(JAWS, stage, regions, allTagged) {
|
||||
var command = new CMD(JAWS, stage, regions, allTagged);
|
||||
return command.run();
|
||||
};
|
||||
|
||||
/**
|
||||
* Command Class
|
||||
* @param JAWS
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
function CMD(JAWS, stage, regions, allTagged) {
|
||||
this._JAWS = JAWS;
|
||||
this._allTagged = allTagged || false;
|
||||
this._stage = stage || null;
|
||||
this._regions = regions || [];
|
||||
this._choices = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* CMD: Run
|
||||
*/
|
||||
|
||||
CMD.prototype.run = Promise.method(function() {
|
||||
|
||||
var _this = this;
|
||||
_this._report = {
|
||||
targetLambdas: 0,
|
||||
targetEndpoints: 0
|
||||
};
|
||||
|
||||
return Promise.try(function() {})
|
||||
.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;
|
||||
} else {
|
||||
|
||||
// TODO: Untag all other resources
|
||||
|
||||
return _this._resources;
|
||||
}
|
||||
})
|
||||
.each(function(resource) {
|
||||
if (resource.type === 'lambda') {
|
||||
_this._report.targetLambdas++;
|
||||
return CMDtag.tag('lambda', resource.value, false);
|
||||
} else if (resource.type === 'endpoint') {
|
||||
_this._report.targetEndpoints++;
|
||||
return CMDtag.tag('endpoint', resource.value, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(_this._promptStage)
|
||||
.then(_this._promptRegion)
|
||||
.then(function() {
|
||||
|
||||
// Status
|
||||
JawsCli.log(chalk.white('-------------------------------------------'));
|
||||
JawsCli.log(chalk.white(' Dashboard: Deploying Lambdas...'));
|
||||
JawsCli.log(chalk.white('-------------------------------------------'));
|
||||
|
||||
return CMDdeployLambda.run(
|
||||
_this._JAWS,
|
||||
_this._stage,
|
||||
_this._regions,
|
||||
true);
|
||||
})
|
||||
.then(function() {
|
||||
|
||||
// Status
|
||||
JawsCli.log(chalk.white('-------------------------------------------'));
|
||||
JawsCli.log(chalk.white(' Dashboard: Deploying Endpoints...'));
|
||||
JawsCli.log(chalk.white('-------------------------------------------'));
|
||||
|
||||
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.findAllJawsJsons(_this._JAWS._meta.projectRootPath)
|
||||
.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: json.lambda.functionName,
|
||||
};
|
||||
|
||||
// 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.endpoint) {
|
||||
module.endpoint = {
|
||||
key: ' E) ',
|
||||
value: jsonPaths[i],
|
||||
type: 'endpoint',
|
||||
label: '/' + json.endpoint.path + ' - ' + json.endpoint.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.project.stages) {
|
||||
|
||||
_this._summary = _this._summary
|
||||
+ chalk.white(' ' + stage + ' ');
|
||||
|
||||
for (var i = 0; i < _this._JAWS._meta.projectJson.project.stages[stage].length; i++) {
|
||||
_this._summary = _this._summary
|
||||
+ chalk.grey(_this._JAWS._meta.projectJson.project.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.project.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],
|
||||
});
|
||||
}
|
||||
|
||||
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.project.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');
|
||||
}
|
||||
|
||||
// If stage only has 1 region, use it and skip prompt
|
||||
if (regions.length === 1) {
|
||||
_this._regions = regions;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create Choices
|
||||
var choices = [];
|
||||
for (var i = 0; i < (_this._regions.length + 1); i++) {
|
||||
|
||||
if (_this._regions[i]) {
|
||||
choices.push({
|
||||
key: (i + 1) + ') ',
|
||||
value: _this._regions[i],
|
||||
label: _this._regions[i],
|
||||
});
|
||||
} else {
|
||||
// Push 'all regions' choice
|
||||
choices.push({
|
||||
key: (i + 1) + ') ',
|
||||
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 = Object.keys(_this._JAWS._meta.projectJson.project.stages[_this._stage]);
|
||||
} else {
|
||||
_this._regions = [results[0].value];
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -1,24 +1,129 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* JAWS Command: deploy api <stage> <region>
|
||||
* - Deploys project's API Gateway REST API to the specified stage and region(s)
|
||||
* JAWS Command: deploy endpoint <stage> <region>
|
||||
* - Deploys project's API Gateway REST API to the specified stage and one or all regions
|
||||
*/
|
||||
|
||||
// TODO: figure out what specific permissions are needed
|
||||
// TODO: Add Concurrent API creation across multiple regions, currently consecutive
|
||||
// TODO: On completion, list API G routes not used within the project (all regions). Offer option to delete them.
|
||||
|
||||
var JawsError = require('../jaws-error'),
|
||||
JawsCli = require('../utils/cli'),
|
||||
Promise = require('bluebird'),
|
||||
fs = require('fs'),
|
||||
os = require('os'),
|
||||
path = require('path'),
|
||||
utils = require('../utils/index'),
|
||||
CMDtag = require('./tag'),
|
||||
JawsAPIClient = require('jaws-api-gateway-client');
|
||||
|
||||
Promise.promisifyAll(fs);
|
||||
|
||||
/**
|
||||
* Api Deployer Class
|
||||
* Run
|
||||
* @param {Jaws} JAWS
|
||||
* @param stage
|
||||
* @returns Promise
|
||||
*/
|
||||
module.exports.run = function(JAWS, stage, regions, allTagged) {
|
||||
var command = new CMD(JAWS, stage, regions, allTagged);
|
||||
return command.run();
|
||||
};
|
||||
|
||||
/**
|
||||
* CMD Class
|
||||
* @param JAWS
|
||||
* @param stage
|
||||
* @param regions
|
||||
* @param allTagged
|
||||
* @constructor
|
||||
*/
|
||||
function CMD(JAWS, stage, regions, allTagged) {
|
||||
var _this = this;
|
||||
_this._stage = stage;
|
||||
_this._regions = regions.length ? regions : Object.keys(this._JAWS._meta.projectJson.project.stages[this._stage]);
|
||||
_this._allTagged = allTagged;
|
||||
_this._JAWS = JAWS;
|
||||
_this._prjJson = JAWS._meta.projectJson;
|
||||
_this._prjRootPath = JAWS._meta.projectRootPath;
|
||||
_this._prjCreds = JAWS._meta.credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* CMD: Run
|
||||
*/
|
||||
CMD.prototype.run = Promise.method(function() {
|
||||
|
||||
var _this = this;
|
||||
|
||||
// Flow
|
||||
return Promise.try(function() {
|
||||
|
||||
// If !allTagged, tag current directory
|
||||
if (!_this._allTagged) {
|
||||
return CMDtag.tag('api', null, false);
|
||||
}
|
||||
})
|
||||
.bind(_this)
|
||||
.then(_this._promptStage)
|
||||
.then(_this._promptRegion)
|
||||
.then(function() {
|
||||
return _this._regions;
|
||||
})
|
||||
.each(function(region) {
|
||||
|
||||
JawsCli.log('Endpoint Deployer: Deploying endpoint(s) to region "' + region + '"...');
|
||||
|
||||
var deployer = new ApiDeployer(
|
||||
_this._stage,
|
||||
region,
|
||||
_this._prjRootPath,
|
||||
_this._prjJson,
|
||||
_this._prjCreds
|
||||
);
|
||||
|
||||
return deployer.deploy()
|
||||
.then(function(url) {
|
||||
JawsCli.log('Endpoint Deployer: Endpoints for stage "'
|
||||
+ _this._stage
|
||||
+ '" successfully deployed to API Gateway in the region "'
|
||||
+ region
|
||||
+ '". Access them @ '
|
||||
+ url);
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
// Untag All tagged endpoints
|
||||
return _this._allTagged ? CMDtag.tagAll(_this._JAWS, 'endpoint', true) : CMDtag.tag('endpoint', null, true);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* CMD: Prompt Stage
|
||||
*/
|
||||
CMD.prototype._promptStage = Promise.resolve(function() {
|
||||
|
||||
// If stage, skip
|
||||
if (_this._stage) return;
|
||||
|
||||
var stages = Object.keys(_this._prjJson.project.stages);
|
||||
if (!stages.length) {
|
||||
throw new JawsError('You have no stages in this project');
|
||||
}
|
||||
|
||||
var choices = [];
|
||||
for (var i = 0; i < stages.length; i++) {
|
||||
choices.push({
|
||||
key: (i + 1) + ': ',
|
||||
value: stages[i]
|
||||
});
|
||||
}
|
||||
|
||||
return JawsCLI.checklist('Select a stage to deploy to: ', choices);
|
||||
});
|
||||
|
||||
/**
|
||||
* Api Deployer
|
||||
* @param stage
|
||||
* @param regions
|
||||
* @param prjJson
|
||||
@ -37,8 +142,16 @@ function ApiDeployer(stage, region, prjRootPath, prjJson, prjCreds) {
|
||||
_this._prjCreds = prjCreds;
|
||||
_this._endpoints = [];
|
||||
_this._resources = [];
|
||||
_this._awsAccountNumber = _this._region.iamRoleArnApiGateway.replace('arn:aws:iam::', '').split(':')[0];
|
||||
_this._restApiId = _this._region.restApiId ? _this._region.restApiId : null;
|
||||
|
||||
// Get Region JSON
|
||||
for (var i = 0; i < _this._prjJson.project.stages[_this._stage].length; i++) {
|
||||
if (_this._region === _this._prjJson.project.stages[_this._stage][i].region) {
|
||||
_this._regionJson = _this._prjJson.project.stages[_this._stage][i];
|
||||
}
|
||||
}
|
||||
|
||||
_this._awsAccountNumber = _this._regionJson.iamRoleArnApiGateway.replace('arn:aws:iam::', '').split(':')[0];
|
||||
_this._restApiId = _this._regionJson.restApiId ? _this._regionJson.restApiId : null;
|
||||
|
||||
// Instantiate API Gateway Client
|
||||
this.ApiClient = new JawsAPIClient({
|
||||
@ -67,7 +180,7 @@ ApiDeployer.prototype.deploy = Promise.method(function() {
|
||||
return 'https://'
|
||||
+ _this._restApiId
|
||||
+ '.execute-api.'
|
||||
+ _this._region.region
|
||||
+ _this._region
|
||||
+ '.amazonaws.com/'
|
||||
+ _this._stage
|
||||
+ '/';
|
||||
@ -95,10 +208,10 @@ ApiDeployer.prototype._findTaggedEndpoints = Promise.method(function() {
|
||||
JawsError.errorCodes.UNKNOWN);
|
||||
}
|
||||
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "'
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "'
|
||||
+ _this._stage + ' - '
|
||||
+ _this._region.region
|
||||
+ _this._region
|
||||
+ '": found '
|
||||
+ _this._endpoints.length + ' endpoints to deploy');
|
||||
});
|
||||
@ -144,7 +257,7 @@ ApiDeployer.prototype._saveApiId = Promise.method(function() {
|
||||
|
||||
// Attach API Gateway REST API ID
|
||||
for (var i = 0; i < _this._prjJson.project.stages[_this._stage].length; i++) {
|
||||
if (_this._prjJson.project.stages[_this._stage][i].region === _this._region.region) {
|
||||
if (_this._prjJson.project.stages[_this._stage][i].region === _this._region) {
|
||||
_this._prjJson.project.stages[_this._stage][i].restApiId = _this._restApiId;
|
||||
}
|
||||
}
|
||||
@ -167,10 +280,10 @@ ApiDeployer.prototype._findOrCreateApi = Promise.method(function() {
|
||||
.then(function(response) {
|
||||
|
||||
_this._restApiId = response.id;
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "'
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "'
|
||||
+ _this._stage + ' - '
|
||||
+ _this._region.region
|
||||
+ _this._region
|
||||
+ '": found existing REST API on AWS API Gateway with ID: '
|
||||
+ response.id);
|
||||
});
|
||||
@ -183,10 +296,10 @@ ApiDeployer.prototype._findOrCreateApi = Promise.method(function() {
|
||||
}).then(function(response) {
|
||||
|
||||
_this._restApiId = response.id;
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "'
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "'
|
||||
+ _this._stage + ' - '
|
||||
+ _this._region.region
|
||||
+ _this._region
|
||||
+ '": created a new REST API on AWS API Gateway with ID: '
|
||||
+ response.id);
|
||||
});
|
||||
@ -215,10 +328,10 @@ ApiDeployer.prototype._listApiResources = Promise.method(function() {
|
||||
}
|
||||
}
|
||||
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "'
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "'
|
||||
+ _this._stage + ' - '
|
||||
+ _this._region.region
|
||||
+ _this._region
|
||||
+ '": found '
|
||||
+ _this._resources.length
|
||||
+ ' existing resources on API Gateway');
|
||||
@ -293,10 +406,10 @@ ApiDeployer.prototype._createEndpointResources = Promise.method(function(endpoin
|
||||
|
||||
// Add resource to _this.resources and callback
|
||||
_this._resources.push(response);
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "' +
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "' +
|
||||
_this._stage + ' - '
|
||||
+ _this._region.region
|
||||
+ _this._region
|
||||
+ ' - ' + endpoint.endpoint.path + '": '
|
||||
+ 'created resource: '
|
||||
+ response.pathPart);
|
||||
@ -368,10 +481,10 @@ ApiDeployer.prototype._createEndpointMethod = Promise.method(function(endpoint)
|
||||
.delay(250) // API Gateway takes time to delete Methods. Might have to increase this.
|
||||
.then(function(response) {
|
||||
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "'
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "'
|
||||
+ _this._stage + ' - '
|
||||
+ _this._region.region
|
||||
+ _this._region
|
||||
+ ' - ' + endpoint.endpoint.path + '": '
|
||||
+ 'created method: '
|
||||
+ endpoint.endpoint.method);
|
||||
@ -394,18 +507,18 @@ ApiDeployer.prototype._createEndpointIntegration = Promise.method(function(endpo
|
||||
httpMethod: 'POST', // Must be post for lambda
|
||||
authorizationType: 'none',
|
||||
uri: 'arn:aws:apigateway:'
|
||||
+ _this._region.region
|
||||
+ ':lambda:path/2015-03-31/functions/arn:aws:lambda:'
|
||||
+ _this._region.region
|
||||
+ ':'
|
||||
+ _this._awsAccountNumber
|
||||
+ ':function:'
|
||||
+ [_this._stage,
|
||||
+ _this._region
|
||||
+ ':lambda:path/2015-03-31/functions/arn:aws:lambda:'
|
||||
+ _this._region
|
||||
+ ':'
|
||||
+ _this._awsAccountNumber
|
||||
+ ':function:'
|
||||
+ [_this._stage,
|
||||
_this._prjJson.name,
|
||||
endpoint.lambda.functionName,
|
||||
].join('_-_').replace(/ /g, '')
|
||||
+ '/invocations',
|
||||
credentials: _this._region.iamRoleArnApiGateway,
|
||||
+ '/invocations',
|
||||
credentials: _this._regionJson.iamRoleArnApiGateway,
|
||||
requestParameters: endpoint.endpoint.requestParameters || {},
|
||||
requestTemplates: endpoint.endpoint.requestTemplates || {},
|
||||
cacheNamespace: endpoint.endpoint.cacheNamespace || null,
|
||||
@ -428,10 +541,10 @@ ApiDeployer.prototype._createEndpointIntegration = Promise.method(function(endpo
|
||||
|
||||
// Save integration to apig property
|
||||
endpoint.endpoint.apig.integration = response;
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "'
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "'
|
||||
+ _this._stage + ' - '
|
||||
+ _this._region.region
|
||||
+ _this._region
|
||||
+ ' - ' + endpoint.endpoint.path + '": '
|
||||
+ 'created integration with the type: '
|
||||
+ endpoint.endpoint.type);
|
||||
@ -476,11 +589,14 @@ ApiDeployer.prototype._createEndpointMethodResponses = Promise.method(function(e
|
||||
thisResponse.statusCode,
|
||||
methodResponseBody)
|
||||
.then(function() {
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "' +
|
||||
_this._stage + ' - ' +
|
||||
_this._region.region
|
||||
+ ' - ' + endpoint.endpoint.path + '": '
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "'
|
||||
+ _this._stage
|
||||
+ ' - '
|
||||
+ _this._region
|
||||
+ ' - '
|
||||
+ endpoint.endpoint.path
|
||||
+ '": '
|
||||
+ 'created method response');
|
||||
})
|
||||
.catch(function(error) {
|
||||
@ -529,11 +645,14 @@ ApiDeployer.prototype._createEndpointMethodIntegResponses = Promise.method(funct
|
||||
thisResponse.statusCode,
|
||||
integrationResponseBody)
|
||||
.then(function() {
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "'
|
||||
+ _this._stage + ' - '
|
||||
+ _this._region.region
|
||||
+ ' - ' + endpoint.endpoint.path + '": '
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "'
|
||||
+ _this._stage
|
||||
+ ' - '
|
||||
+ _this._region
|
||||
+ ' - '
|
||||
+ endpoint.endpoint.path
|
||||
+ '": '
|
||||
+ 'created method integration response');
|
||||
}).catch(function(error) {
|
||||
throw new JawsError(
|
||||
@ -575,11 +694,14 @@ ApiDeployer.prototype._createEndpointMethodResponses = Promise.method(function(e
|
||||
thisResponse.statusCode,
|
||||
methodResponseBody)
|
||||
.then(function() {
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "'
|
||||
+ _this._stage + ' - '
|
||||
+ _this._region.region
|
||||
+ ' - ' + endpoint.endpoint.path + '": '
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "'
|
||||
+ _this._stage
|
||||
+ ' - '
|
||||
+ _this._region
|
||||
+ ' - '
|
||||
+ endpoint.endpoint.path
|
||||
+ '": '
|
||||
+ 'created method response');
|
||||
})
|
||||
.catch(function(error) {
|
||||
@ -628,11 +750,14 @@ ApiDeployer.prototype._createEndpointMethodIntegResponses = Promise.method(funct
|
||||
thisResponse.statusCode,
|
||||
integrationResponseBody)
|
||||
.then(function() {
|
||||
utils.logIfVerbose(
|
||||
'API Gateway: "'
|
||||
+ _this._stage + ' - '
|
||||
+ _this._region.region
|
||||
+ ' - ' + endpoint.endpoint.path + '": '
|
||||
JawsCli.log(
|
||||
'Endpoint Deployer: "'
|
||||
+ _this._stage
|
||||
+ ' - '
|
||||
+ _this._region
|
||||
+ ' - '
|
||||
+ endpoint.endpoint.path
|
||||
+ '": '
|
||||
+ 'created method integration response');
|
||||
}).catch(function(error) {
|
||||
throw new JawsError(
|
||||
@ -664,84 +789,4 @@ ApiDeployer.prototype._createDeployment = Promise.method(function() {
|
||||
error.message,
|
||||
JawsError.errorCodes.UNKNOWN);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Deploy API
|
||||
*
|
||||
* @param {Jaws} JAWS
|
||||
* @param stage
|
||||
* @returns {bluebird|exports|module.exports}
|
||||
*/
|
||||
module.exports.deployApi = function(JAWS, stage, region, allTagged) {
|
||||
|
||||
// Check region (required)
|
||||
if (!region) {
|
||||
Promise.reject(new JawsError(
|
||||
'Must specify a region',
|
||||
JawsError.errorCodes.UNKNOWN));
|
||||
}
|
||||
|
||||
// Check stage exists
|
||||
stage = stage.toLowerCase().trim();
|
||||
if (!JAWS._meta.projectJson.project.stages[stage]) {
|
||||
Promise.reject(new JawsError(
|
||||
'The stage "' + stage
|
||||
+ '" does not exist. Please generate this stage if you would like to deploy to it.',
|
||||
JawsError.errorCodes.UNKNOWN));
|
||||
}
|
||||
|
||||
// Check if stage has regions
|
||||
if (!JAWS._meta.projectJson.project.stages[stage].length) {
|
||||
Promise.reject(new JawsError(
|
||||
'You do not have any regions set for this stage. Add one before deploying.',
|
||||
JawsError.errorCodes.UNKNOWN));
|
||||
}
|
||||
|
||||
var tagCmd = require('./tag');
|
||||
|
||||
// Tag CWD if necessary
|
||||
return (allTagged ? Promise.resolve() : tagCmd.tag('api', null, false))
|
||||
.then(function() {
|
||||
|
||||
// Validate region. If no region specified, deploy to all regions
|
||||
if (!region) {
|
||||
|
||||
var regions = JAWS._meta.projectJson.project.stages[stage];
|
||||
} else {
|
||||
|
||||
region = region.toLowerCase().trim();
|
||||
|
||||
for (var i = 0; i < JAWS._meta.projectJson.project.stages[stage].length; i++) {
|
||||
var tempRegion = JAWS._meta.projectJson.project.stages[stage][i];
|
||||
if (region === tempRegion.region) var regions = [tempRegion];
|
||||
}
|
||||
|
||||
// If missing region, throw error
|
||||
if (!regions) {
|
||||
throw new JawsError(
|
||||
'The region "' + region + '" does not exist in this stage.',
|
||||
JawsError.errorCodes.UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
return regions;
|
||||
})
|
||||
.each(function(region) {
|
||||
|
||||
var deployer = new ApiDeployer(
|
||||
stage,
|
||||
region,
|
||||
JAWS._meta.projectRootPath,
|
||||
JAWS._meta.projectJson,
|
||||
JAWS._meta.credentials
|
||||
);
|
||||
return deployer.deploy()
|
||||
.then(function(url) {
|
||||
console.log('API Gateway successfully deployed: ' + url);
|
||||
|
||||
// Untag
|
||||
return allTagged ? tagCmd.tagAll(JAWS, 'api', true) : tagCmd.tag('api', null, true);
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,7 @@
|
||||
|
||||
// Defaults
|
||||
var JawsError = require('../jaws-error'),
|
||||
JawsCLI = require('../utils/jaws-cli')
|
||||
Promise = require('bluebird'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
|
||||
@ -1,329 +1,409 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* JAWS Command: new
|
||||
* JAWS Command: new project
|
||||
* - Asks the user for information about their new JAWS project
|
||||
* - Creates a new project in the current working directory
|
||||
* - Creates IAM resources via CloudFormation
|
||||
*/
|
||||
|
||||
// TODO: Add region into jaws-cf template using pseudo params via CF
|
||||
|
||||
// Defaults
|
||||
var JawsError = require('../jaws-error'),
|
||||
JawsCLI = require('../utils/cli'),
|
||||
Promise = require('bluebird'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
os = require('os'),
|
||||
AWSUtils = require('../utils/aws'),
|
||||
utils = require('../utils'),
|
||||
inquirer = require('bluebird-inquirer'),
|
||||
chalk = require('chalk'),
|
||||
shortid = require('shortid'),
|
||||
extend = require('util')._extend, //OK per Isaacs and http://stackoverflow.com/a/22286375/563420
|
||||
Spinner = require('cli-spinner').Spinner;
|
||||
shortid = require('shortid');
|
||||
|
||||
Promise.promisifyAll(fs);
|
||||
|
||||
// Define Project
|
||||
var project = {};
|
||||
|
||||
/**
|
||||
* Generate ASCII
|
||||
* @return string
|
||||
* Run
|
||||
* @param name
|
||||
* @param stage
|
||||
* @param s3Bucket
|
||||
* @param notificationEmail
|
||||
* @param region
|
||||
* @param profile
|
||||
* @param noCf
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
function _generateAscii() {
|
||||
module.exports.run = function(name, stage, s3Bucket, notificationEmail, region, profile, noCf) {
|
||||
var command = new CMD(
|
||||
name,
|
||||
stage,
|
||||
s3Bucket,
|
||||
notificationEmail,
|
||||
region,
|
||||
profile,
|
||||
noCf);
|
||||
return command.run();
|
||||
};
|
||||
|
||||
var art = '';
|
||||
art = art + ' ____ _____ __ __ _________ ' + os.EOL;
|
||||
art = art + ' | | / _ \\/ \\ / \\/ _____/ ' + os.EOL;
|
||||
art = art + ' | |/ /_\\ \\ \\/\\/ /\\_____ \\ ' + os.EOL;
|
||||
art = art + ' /\\__| / | \\ / / \\ ' + os.EOL;
|
||||
art = art + ' \\________\\____|__ /\\__/\\__/ /_________/ ' + os.EOL;
|
||||
art = art + '' + os.EOL;
|
||||
art = art + ' *** The Server-less Framework *** ' + os.EOL;
|
||||
/**
|
||||
* CMD Class
|
||||
* @param name
|
||||
* @param stage
|
||||
* @param s3Bucket
|
||||
* @param notificationEmail
|
||||
* @param region
|
||||
* @param profile
|
||||
* @param noExeCf
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
return art;
|
||||
function CMD(name, stage, s3Bucket, notificationEmail, region, profile, noCf) {
|
||||
|
||||
// Defaults
|
||||
this._name = name ? name : null;
|
||||
this._stage = stage ? stage.toLowerCase().replace(/\W+/g, '').substring(0, 15) : null;
|
||||
this._s3Bucket = s3Bucket;
|
||||
this._notificationEmail = notificationEmail;
|
||||
this._region = region;
|
||||
this._profile = profile;
|
||||
this._noCf = noCf;
|
||||
this._prompts = {
|
||||
properties: {},
|
||||
};
|
||||
this.Prompter = JawsCLI.prompt();
|
||||
this.Prompter.override = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Answers
|
||||
*
|
||||
* @returns {Promise}
|
||||
* @private
|
||||
* CMD: Run
|
||||
*/
|
||||
function _getAnswers(projName, stage, s3Bucket, lambdaRegion, notificationEmail, awsProfile) {
|
||||
// Greet
|
||||
console.log(chalk.yellow(_generateAscii()));
|
||||
|
||||
// Define CLI prompts
|
||||
var prompts = [],
|
||||
overrideAnswers = {};
|
||||
CMD.prototype.run = Promise.method(function() {
|
||||
|
||||
if (!projName) {
|
||||
prompts.push({
|
||||
type: 'input',
|
||||
name: 'name',
|
||||
message: 'Type a name for your new project (max 20 chars. Aphanumeric and - only):',
|
||||
default: 'jaws-new',
|
||||
});
|
||||
} else {
|
||||
overrideAnswers.name = projName;
|
||||
var _this = this;
|
||||
|
||||
return Promise.try(function() {
|
||||
|
||||
// ASCII Greeting
|
||||
JawsCLI.ascii();
|
||||
|
||||
})
|
||||
.bind(_this)
|
||||
.then(_this._prompt)
|
||||
.then(_this._prepareProjectData)
|
||||
.then(_this._createS3JawsStructure) //see if bucket is avail first before doing work
|
||||
.then(_this._createProjectDirectory)
|
||||
.then(function() {
|
||||
if (!_this._noCf) {
|
||||
return _this._createCfStack();
|
||||
} else {
|
||||
utils.logIfVerbose('No exec cf specified, updating proj jaws.json only');
|
||||
JawsCLI.log('Project and env var file in s3 successfully created. CloudFormation file can be run manually');
|
||||
JawsCLI.log('After creating CF stack, remember to put the IAM role outputs in your project jaws.json');
|
||||
}
|
||||
})
|
||||
.then(_this._createProjectJson);
|
||||
});
|
||||
|
||||
/**
|
||||
* CMD: Prompt
|
||||
*/
|
||||
|
||||
CMD.prototype._prompt = Promise.method(function() {
|
||||
|
||||
var _this = this;
|
||||
|
||||
// Prompt: name (project name)
|
||||
_this.Prompter.override.name = _this._name;
|
||||
_this._prompts.properties.name = {
|
||||
description: 'Enter a project name: '.yellow,
|
||||
default: 'jaws-' + shortid.generate().replace(/\W+/g, '').substring(0, 19),
|
||||
message: 'Name must be only letters, numbers, underscores or dashes',
|
||||
conform: function(name) {
|
||||
var re = /^[a-zA-Z0-9-_]+$/;
|
||||
return re.test(name);
|
||||
},
|
||||
};
|
||||
|
||||
// Prompt: stage
|
||||
_this.Prompter.override.stage = _this._stage;
|
||||
_this._prompts.properties.stage = {
|
||||
description: 'Enter a stage for this project: '.yellow,
|
||||
default: 'dev',
|
||||
message: 'Stage must be letters only',
|
||||
conform: function(stage) {
|
||||
var re = /^[a-zA-Z]+$/;
|
||||
return re.test(stage);
|
||||
},
|
||||
};
|
||||
|
||||
// Prompt: s3 bucket - holds env vars for this project
|
||||
_this.Prompter.override.s3Bucket = _this._s3Bucket;
|
||||
_this._prompts.properties.s3Bucket = {
|
||||
description: 'Enter an AWS S3 Bucket name to store this project\'s env vars: '.yellow,
|
||||
default: 'jaws.yourapp.com',
|
||||
message: 'Bucket name must only contain lowercase letters, numbers, periods and dashes',
|
||||
conform: function(bucket) {
|
||||
var re = /^[a-z0-9-.]+$/;
|
||||
return re.test(bucket);
|
||||
},
|
||||
};
|
||||
|
||||
// Prompt: notification email - for AWS alerts
|
||||
_this.Prompter.override.notificationEmail = _this._notificationEmail;
|
||||
_this._prompts.properties.notificationEmail = {
|
||||
description: 'Enter an email to use for AWS alarms: '.yellow,
|
||||
required: true,
|
||||
message: 'Please enter a valid email',
|
||||
default: 'you@yourapp.com',
|
||||
conform: function(email) {
|
||||
if (!email) return false;
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
// Prompt: API Keys - Create an AWS profile by entering API keys
|
||||
if (!fs.existsSync(path.join(AWSUtils.getConfigDir(), 'credentials'))) {
|
||||
|
||||
_this.Prompter.override.awsAdminKeyId = _this._awsAdminKeyId;
|
||||
_this._prompts.properties.awsAdminKeyId = {
|
||||
description: 'Enter the ACCESS KEY ID for your Admin AWS IAM User: '.yellow,
|
||||
required: true,
|
||||
message: 'Please enter a valid access key ID',
|
||||
conform: function(key) {
|
||||
if (!key) return false;
|
||||
return true;
|
||||
},
|
||||
};
|
||||
_this.Prompter.override.awsAdminSecretKey = _this._awsAdminSecretKey;
|
||||
_this._prompts.properties.awsAdminSecretKey = {
|
||||
description: 'Enter the SECRET ACCESS KEY for your Admin AWS IAM User: '.yellow,
|
||||
required: true,
|
||||
message: 'Please enter a valid secret access key',
|
||||
conform: function(key) {
|
||||
if (!key) return false;
|
||||
return true;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (!stage) {
|
||||
prompts.push({
|
||||
type: 'input',
|
||||
name: 'stage',
|
||||
message: 'Which stage would you like to create? (you can import more later)',
|
||||
default: 'dev',
|
||||
// Show Prompts
|
||||
return new Promise(function(resolve, reject) {
|
||||
_this.Prompter.get(_this._prompts, function(err, answers) {
|
||||
if (err) {
|
||||
reject(new JawsError(err));
|
||||
}
|
||||
resolve(answers);
|
||||
});
|
||||
} else {
|
||||
overrideAnswers.stage = stage;
|
||||
}
|
||||
})
|
||||
.then(function(answers) {
|
||||
|
||||
if (!s3Bucket) {
|
||||
prompts.push({
|
||||
type: 'input',
|
||||
name: 's3Bucket',
|
||||
message: 'What bucket should be used to store JAWS env var files for this project? (/JAWS/envVars/<stage> file ' +
|
||||
'will be created. This bucket should be specific to this project.)',
|
||||
default: 'jawsproject.yourdomain.com',
|
||||
});
|
||||
} else {
|
||||
overrideAnswers.s3Bucket = s3Bucket;
|
||||
}
|
||||
// Set Answers
|
||||
_this._name = answers.name;
|
||||
_this._stage = answers.stage.toLowerCase();
|
||||
_this._s3Bucket = answers.s3Bucket;
|
||||
_this._notificationEmail = answers.notificationEmail;
|
||||
_this._awsAdminKeyId = answers.awsAdminKeyId;
|
||||
_this._awsAdminSecretKey = answers.awsAdminSecretKey;
|
||||
|
||||
// Request Region - Only available AWS Lambda regions allowed
|
||||
if (!lambdaRegion) {
|
||||
prompts.push({
|
||||
type: 'rawlist',
|
||||
name: 'region',
|
||||
message: 'Which AWS Region would you like to use (can add more/change later)?',
|
||||
default: 'us-east-1',
|
||||
choices: [
|
||||
'us-east-1',
|
||||
'us-west-1',
|
||||
'eu-west-1',
|
||||
'ap-northeast-1',
|
||||
],
|
||||
});
|
||||
} else {
|
||||
overrideAnswers.region = lambdaRegion;
|
||||
}
|
||||
// If region exists, skip select prompt
|
||||
if (_this._region) return Promise.resolve();
|
||||
|
||||
if (!notificationEmail) {
|
||||
prompts.push({
|
||||
type: 'input',
|
||||
name: 'notificationEmail',
|
||||
message: 'Email would you like to use for AWS alarms:',
|
||||
default: '',
|
||||
});
|
||||
} else {
|
||||
overrideAnswers.notificationEmail = notificationEmail;
|
||||
}
|
||||
// Prompt: region select
|
||||
var choices = [
|
||||
{ key: '1) ', label: 'us-east-1', value: 'us-east-1' },
|
||||
{ key: '2) ', label: 'us-west-1', value: 'us-west-1' },
|
||||
{ key: '3) ', label: 'eu-east-1', value: 'eu-west-1' },
|
||||
{ key: '4) ', label: 'ap-northeast-1', value: 'ap-northeast-1' },
|
||||
];
|
||||
|
||||
// Use existing or create new AWS CLI profile
|
||||
if (fs.existsSync(path.join(AWSUtils.getConfigDir(), 'credentials'))) {
|
||||
return JawsCLI.select('Select a region for your project: ', choices, false)
|
||||
.then(function(results) {
|
||||
_this._region = results[0].value;
|
||||
return Promise.resolve();
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
|
||||
var profilesList = AWSUtils.profilesMap(),
|
||||
profiles = Object.keys(profilesList);
|
||||
// If profile exists, skip select prompt
|
||||
if (_this._profile) return Promise.resolve();
|
||||
|
||||
if (awsProfile && -1 !== profiles.indexOf(awsProfile)) {
|
||||
overrideAnswers.awsProfile = awsProfile;
|
||||
} else {
|
||||
prompts.unshift({
|
||||
type: 'rawlist',
|
||||
name: 'awsProfile',
|
||||
message: 'What AWS profile in ~/.aws/credentials should be used for your admin user?:',
|
||||
choices: profiles,
|
||||
default: profiles[0],
|
||||
// Prompt: profile select
|
||||
var profilesList = AWSUtils.profilesMap(),
|
||||
profiles = Object.keys(profilesList),
|
||||
choices = [];
|
||||
|
||||
for (var i = 0; i < profiles.length; i++) {
|
||||
choices.push({
|
||||
key: (i + 1) + ') ',
|
||||
value: profiles[i],
|
||||
label: profiles[i],
|
||||
});
|
||||
}
|
||||
|
||||
return JawsCLI.select('Select a profile for your project: ', choices, false)
|
||||
.then(function(results) {
|
||||
_this._profile = results[0].value;
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
prompts.unshift({ //need to create aws creds profile (will use 'default')
|
||||
type: 'input',
|
||||
name: 'awsAdminKeyId',
|
||||
message: 'Please enter the ACCESS KEY ID for your ADMIN AWS IAM User:',
|
||||
}, {
|
||||
type: 'input',
|
||||
name: 'awsAdminSecretKey',
|
||||
message: 'Please enter the SECRET ACCESS KEY for your ADMIN AWS IAM User:',
|
||||
});
|
||||
}
|
||||
|
||||
if (prompts.length > 0) {
|
||||
return inquirer.prompt(prompts)
|
||||
.then(function(answers) {
|
||||
return extend(answers, overrideAnswers);
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve(overrideAnswers);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Prepare project data
|
||||
*
|
||||
* @param answers
|
||||
* CMD: Prepare Project Data
|
||||
* @returns {Promise}
|
||||
* @private
|
||||
*/
|
||||
function _prepareProjectData(answers) {
|
||||
if (answers.stage.toLowerCase() == 'local') {
|
||||
Promise.reject(new JawsError(
|
||||
'Stage ' + answers.stage + ' is reserved',
|
||||
JawsError.errorCodes.UNKNOWN));
|
||||
|
||||
CMD.prototype._prepareProjectData = Promise.method(function() {
|
||||
|
||||
var _this = this;
|
||||
|
||||
// Validate: Ensure stage isn't "local"
|
||||
if (_this._stage.toLowerCase() == 'local') {
|
||||
throw new JawsError('Stage ' + _this._stage + ' is reserved');
|
||||
}
|
||||
|
||||
project.name = answers.name.toLowerCase().trim()
|
||||
.replace(/[^a-zA-Z-\d\s:]/g, '')
|
||||
.replace(/\s/g, '-')
|
||||
.substring(0, 19);
|
||||
|
||||
// AWS only allows Alphanumeric and - in name
|
||||
var nameOk = /^([a-zA-Z0-9-]+)$/.exec(project.name);
|
||||
// Validate: AWS only allows Alphanumeric and - in name
|
||||
var nameOk = /^([a-zA-Z0-9-]+)$/.exec(_this._name);
|
||||
if (!nameOk) {
|
||||
Promise.reject(new JawsError(
|
||||
'Project names can only be alphanumeric and -',
|
||||
JawsError.errorCodes.INVALID_PROJ_NAME));
|
||||
throw new JawsError('Project names can only be alphanumeric and -');
|
||||
}
|
||||
|
||||
// Append unique id if name is in use
|
||||
if (fs.existsSync(path.join(process.cwd(), project.name))) {
|
||||
project.name = project.name + '-' + shortid.generate().replace(/[_-]/g, '');
|
||||
if (fs.existsSync(path.join(process.cwd(), _this._name))) {
|
||||
_this._name = _this._name + '-' + shortid.generate().replace(/\W+/g, '').substring(0, 19);
|
||||
}
|
||||
|
||||
// Set or Create Profile
|
||||
if (answers.awsProfile) {
|
||||
// Validate: If no profile, ensure access keys, create profile
|
||||
if (!_this._profile) {
|
||||
|
||||
project.awsProfile = answers.awsProfile;
|
||||
|
||||
} else {
|
||||
|
||||
if (!answers.awsAdminKeyId) {
|
||||
reject(new JawsError(
|
||||
if (!_this._awsAdminKeyId) {
|
||||
throw new JawsError(
|
||||
'An AWS Access Key ID is required',
|
||||
JawsError.errorCodes.MISSING_AWS_CREDS));
|
||||
JawsError.errorCodes.MISSING_AWS_CREDS);
|
||||
}
|
||||
|
||||
if (!answers.awsAdminSecretKey) {
|
||||
reject(new JawsError(
|
||||
if (!_this._awsAdminSecretKey) {
|
||||
throw new JawsError(
|
||||
'An AWS Secret Key is required',
|
||||
JawsError.errorCodes.MISSING_AWS_CREDS));
|
||||
JawsError.errorCodes.MISSING_AWS_CREDS);
|
||||
}
|
||||
|
||||
// Set profile
|
||||
AWSUtils.profilesSet('default', answers.region, answers.awsAdminKeyId, answers.awsAdminSecretKey);
|
||||
project.awsProfile = 'default';
|
||||
AWSUtils.profilesSet('default', _this._region, _this._awsAdminKeyId, _this._awsAdminSecretKey);
|
||||
_this._profile = 'default';
|
||||
}
|
||||
|
||||
// Set other project data
|
||||
project.stage = answers.stage;
|
||||
project.region = answers.region;
|
||||
project.notificationEmail = answers.notificationEmail.trim();
|
||||
project.s3Bucket = answers.s3Bucket;
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
* CMD: Create Project Directory
|
||||
* @returns {Promise}
|
||||
* @private
|
||||
*/
|
||||
function _createProjectDirectory() {
|
||||
|
||||
// Set Root Path
|
||||
project.rootPath = path.resolve(path.join(path.dirname('.'), project.name));
|
||||
CMD.prototype._createProjectDirectory = Promise.method(function() {
|
||||
|
||||
var _this = this;
|
||||
|
||||
_this._projectRootPath = path.resolve(path.join(path.dirname('.'), _this._name));
|
||||
|
||||
// Prepare admin.env
|
||||
var adminEnv = 'ADMIN_AWS_PROFILE=' + project.awsProfile + os.EOL;
|
||||
var adminEnv = 'ADMIN_AWS_PROFILE=' + _this._profile + os.EOL;
|
||||
|
||||
// Prepare CloudFormation template
|
||||
var cfTemplate = require('../templates/jaws-cf');
|
||||
cfTemplate.Parameters.aaProjectName.Default = project.name;
|
||||
cfTemplate.Parameters.aaProjectName.AllowedValues = [project.name];
|
||||
cfTemplate.Parameters.aaStage.Default = project.stage;
|
||||
cfTemplate.Parameters.aaDataModelPrefix.Default = project.stage; //to simplify bootstrap use same stage
|
||||
cfTemplate.Parameters.aaNotficationEmail.Default = project.notificationEmail;
|
||||
cfTemplate.Parameters.aaProjectName.Default = _this._name;
|
||||
cfTemplate.Parameters.aaProjectName.AllowedValues = [_this._name];
|
||||
cfTemplate.Parameters.aaStage.Default = _this._stage;
|
||||
cfTemplate.Parameters.aaDataModelPrefix.Default = _this._stage; //to simplify bootstrap use same stage
|
||||
cfTemplate.Parameters.aaNotficationEmail.Default = _this._notificationEmail;
|
||||
|
||||
// Create files
|
||||
// Create Project Scaffolding
|
||||
return utils.writeFile(
|
||||
path.join(project.rootPath, 'back', '.env'),
|
||||
'JAWS_STAGE=' + project.stage + '\nJAWS_DATA_MODEL_PREFIX=' + project.stage
|
||||
)
|
||||
path.join(_this._projectRootPath, 'back', '.env'),
|
||||
'JAWS_STAGE=' + _this._stage
|
||||
+ '\nJAWS_DATA_MODEL_PREFIX=' + _this._stage)
|
||||
.then(function() {
|
||||
return Promise.all([
|
||||
fs.mkdirAsync(path.join(project.rootPath, 'front')),
|
||||
fs.mkdirAsync(path.join(project.rootPath, 'tests')),
|
||||
fs.mkdirAsync(path.join(project.rootPath, 'back/lambdas')),
|
||||
fs.mkdirAsync(path.join(project.rootPath, 'back/lib')),
|
||||
utils.writeFile(path.join(project.rootPath, 'admin.env'), adminEnv),
|
||||
utils.writeFile(path.join(project.rootPath, 'jaws-cf.json'), JSON.stringify(cfTemplate, null, 2)),
|
||||
fs.mkdirAsync(path.join(_this._projectRootPath, 'front')),
|
||||
fs.mkdirAsync(path.join(_this._projectRootPath, 'tests')),
|
||||
fs.mkdirAsync(path.join(_this._projectRootPath, 'back/lambdas')),
|
||||
fs.mkdirAsync(path.join(_this._projectRootPath, 'back/lib')),
|
||||
utils.writeFile(path.join(_this._projectRootPath, 'admin.env'), adminEnv),
|
||||
utils.writeFile(path.join(_this._projectRootPath, 'jaws-cf.json'), JSON.stringify(cfTemplate, null, 2)),
|
||||
]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Create s3 bucket (if DNE) and upload the 1st stage env var
|
||||
*
|
||||
* Format: <bucket>/JAWS/envVars/<projName>/<stage>
|
||||
* CMD Create S3 Bucket
|
||||
* (if DNE) and upload the 1st stage env var
|
||||
* Format: <bucket>/JAWS/envVars/<name>/<stage>
|
||||
*
|
||||
* @returns {Promise}
|
||||
* @private
|
||||
*/
|
||||
function _createS3JawsStructure() {
|
||||
return AWSUtils.createBucket(project.awsProfile, project.region, project.s3Bucket)
|
||||
|
||||
CMD.prototype._createS3JawsStructure = Promise.method(function() {
|
||||
|
||||
var _this = this;
|
||||
|
||||
return AWSUtils.createBucket(_this._profile, _this._region, _this._s3Bucket)
|
||||
.then(function() {
|
||||
var envFileContents = 'JAWS_STAGE=' + project.stage + '\nJAWS_DATA_MODEL_PREFIX=' + project.stage;
|
||||
|
||||
var envFileContents = 'JAWS_STAGE=' + _this._stage
|
||||
+ '\nJAWS_DATA_MODEL_PREFIX=' + _this._stage;
|
||||
|
||||
return AWSUtils.putEnvFile(
|
||||
project.awsProfile,
|
||||
project.region,
|
||||
project.s3Bucket,
|
||||
project.name,
|
||||
project.stage,
|
||||
_this._profile,
|
||||
_this._region,
|
||||
_this._s3Bucket,
|
||||
_this._name,
|
||||
_this._stage,
|
||||
envFileContents);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Create CloudFormation Stack
|
||||
* CMD: Create CloudFormation Stack
|
||||
*/
|
||||
|
||||
function _createCfStack() {
|
||||
CMD.prototype._createCfStack = Promise.method(function() {
|
||||
|
||||
var _this = this;
|
||||
|
||||
// Show loading messages
|
||||
var message = 'JAWS is now going to create an AWS CloudFormation Stack for the "' + project.stage +
|
||||
var message = 'JAWS is now going to create an AWS CloudFormation Stack for the "' + _this._stage +
|
||||
'" stage of your JAWS project. This doesn\'t cost anything, but takes around 5 minutes to set-up. Sit tight!';
|
||||
var spinner = new Spinner('%s Creating CloudFormation Stack...');
|
||||
|
||||
console.log(message);
|
||||
spinner.setSpinnerString('|/-\\');
|
||||
// Start loading icon
|
||||
var spinner = JawsCLI.spinner('Creating CloudFormation Stack for your new project...');
|
||||
spinner.start();
|
||||
|
||||
// Create CF stack
|
||||
return AWSUtils.cfCreateStack(
|
||||
project.awsProfile,
|
||||
project.region,
|
||||
project.rootPath,
|
||||
project.name,
|
||||
project.stage,
|
||||
project.notificationEmail
|
||||
)
|
||||
_this._profile,
|
||||
_this._region,
|
||||
_this._projectRootPath,
|
||||
_this._name,
|
||||
_this._stage,
|
||||
_this._notificationEmail)
|
||||
.then(function(cfData) {
|
||||
return AWSUtils.monitorCfCreate(cfData, project.awsProfile, project.region, spinner);
|
||||
return AWSUtils.monitorCfCreate(cfData, _this._profile, _this._region, spinner);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Create Project JSON
|
||||
* CMD: Create Project JSON
|
||||
*
|
||||
* @param cfOutputs. Optional
|
||||
* @returns {Promise} jaws json js obj
|
||||
* @private
|
||||
*/
|
||||
function _createProjectJson(cfOutputs) {
|
||||
|
||||
CMD.prototype._createProjectJson = Promise.method(function(cfOutputs) {
|
||||
|
||||
var _this = this;
|
||||
|
||||
var iamRoleArnLambda,
|
||||
iamRoleArnApiGateway;
|
||||
@ -341,64 +421,33 @@ function _createProjectJson(cfOutputs) {
|
||||
}
|
||||
|
||||
var jawsJson = {
|
||||
name: project.name,
|
||||
name: _this._name,
|
||||
version: '0.0.1',
|
||||
location: '<enter project\'s github repository url here>',
|
||||
author: 'Vera D. Servers <vera@gmail.com> http://vera.io',
|
||||
description: project.name + ': An ambitious, server-less application built with the JAWS framework.',
|
||||
author: 'You <you@yourapp.com>',
|
||||
description: _this._name + ': An ambitious, server-less application built with the JAWS framework.',
|
||||
project: {
|
||||
stages: {},
|
||||
},
|
||||
};
|
||||
|
||||
jawsJson.project.stages[project.stage] = [];
|
||||
jawsJson.project.stages[project.stage].push({
|
||||
region: project.region,
|
||||
jawsJson.project.stages[_this._stage] = [];
|
||||
jawsJson.project.stages[_this._stage].push({
|
||||
region: _this._region,
|
||||
iamRoleArnLambda: iamRoleArnLambda || '',
|
||||
iamRoleArnApiGateway: iamRoleArnApiGateway || '',
|
||||
});
|
||||
|
||||
jawsJson.project.envVarBucket = {
|
||||
name: project.s3Bucket,
|
||||
region: project.region,
|
||||
name: _this._s3Bucket,
|
||||
region: _this._region,
|
||||
};
|
||||
|
||||
fs.writeFileSync(path.join(project.rootPath, 'jaws.json'), JSON.stringify(jawsJson, null, 2));
|
||||
fs.writeFileSync(path.join(_this._projectRootPath, 'jaws.json'),
|
||||
JSON.stringify(jawsJson, null, 2));
|
||||
|
||||
console.log('Your project "' +
|
||||
project.name +
|
||||
'" has been successfully created in the current directory.'
|
||||
);
|
||||
JawsCLI.log('Your project "' + _this._name
|
||||
+ '" has been successfully created in the current directory.');
|
||||
|
||||
return Promise.resolve(jawsJson);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param projName
|
||||
* @param stage
|
||||
* @param s3Bucket store things like env vars: <bucket>/JAWS/envVars/<proj-name>/<stage>. Create bucket if DNE
|
||||
* @param lambdaRegion
|
||||
* @param notificationEmail
|
||||
* @param awsProfile
|
||||
* @param noExeCf don't execute CloudFormation at the end
|
||||
* @returns {*}
|
||||
*/
|
||||
module.exports.create = function(projName, stage, s3Bucket, lambdaRegion, notificationEmail, awsProfile, noExeCf) {
|
||||
return _getAnswers(projName, stage, s3Bucket, lambdaRegion, notificationEmail, awsProfile)
|
||||
.then(_prepareProjectData)
|
||||
.then(_createS3JawsStructure) //see if bucket is avail first before doing work
|
||||
.then(_createProjectDirectory)
|
||||
.then(function() {
|
||||
if (noExeCf) {
|
||||
utils.logIfVerbose('No exec cf specified, updating proj jaws.json only');
|
||||
console.log('Project and env var file in s3 successfully created. CloudFormation file can be run manually');
|
||||
console.log('After creating CF stack, remember to put the IAM role outputs in your project jaws.json');
|
||||
|
||||
return _createProjectJson();
|
||||
} else {
|
||||
return _createCfStack()
|
||||
.then(_createProjectJson);
|
||||
}
|
||||
});
|
||||
};
|
||||
return jawsJson;
|
||||
});
|
||||
@ -17,15 +17,15 @@ Promise.promisifyAll(fs);
|
||||
/**
|
||||
* Tag a lambda for deployment (set deploy = true)
|
||||
*
|
||||
* @param type api|lambda
|
||||
* @param type endpoint|lambda
|
||||
* @param fullPathToJawsJson optional. Uses cwd by default
|
||||
* @param {boolean} untag. default false
|
||||
* @returns {Promise} full path to jaws.json that was updated
|
||||
*/
|
||||
module.exports.tag = function(type, fullPathToJawsJson, untag) {
|
||||
untag = !!(untag);
|
||||
|
||||
var jawsJsonPath = fullPathToJawsJson || path.join(process.cwd(), 'jaws.json');
|
||||
untag = !!(untag);
|
||||
var jawsJsonPath = fullPathToJawsJson ? fullPathToJawsJson : path.join(process.cwd(), 'jaws.json');
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!fs.existsSync(jawsJsonPath)) {
|
||||
@ -38,7 +38,7 @@ module.exports.tag = function(type, fullPathToJawsJson, untag) {
|
||||
var jawsJson = require(jawsJsonPath);
|
||||
if (type === 'lambda' && typeof jawsJson.lambda !== 'undefined') {
|
||||
jawsJson.lambda.deploy = !untag;
|
||||
} else if (type === 'api' && typeof jawsJson.endpoint !== 'undefined') {
|
||||
} else if (type === 'endpoint' && typeof jawsJson.endpoint !== 'undefined') {
|
||||
jawsJson.endpoint.deploy = !untag;
|
||||
} else {
|
||||
reject(new JawsError(
|
||||
@ -56,7 +56,7 @@ module.exports.tag = function(type, fullPathToJawsJson, untag) {
|
||||
* Tag or untag all
|
||||
*
|
||||
* @param {Jaws} JAWS
|
||||
* @prams type api|lambda
|
||||
* @prams type endpoint|lambda
|
||||
* @param {boolean} untag default false
|
||||
* @returns {Promise}
|
||||
*/
|
||||
@ -66,14 +66,14 @@ module.exports.tagAll = function(JAWS, type, untag) {
|
||||
findAllFunc = (type == 'lambda') ? 'findAllLambdas' : 'findAllEndpoints';
|
||||
|
||||
return utils[findAllFunc](JAWS._meta.projectRootPath)
|
||||
.then(function(lJawsJsonPaths) {
|
||||
.then(function(jawsJsonPaths) {
|
||||
var tagQueue = [];
|
||||
if (!lJawsJsonPaths) {
|
||||
if (!jawsJsonPaths) {
|
||||
throw new JawsError('Could not find any lambdas', JawsError.errorCodes.UNKNOWN);
|
||||
}
|
||||
|
||||
lJawsJsonPaths.forEach(function(ljp) {
|
||||
tagQueue.push(_this.tag(type, ljp, untag));
|
||||
jawsJsonPaths.forEach(function(jawsJsonPath) {
|
||||
tagQueue.push(_this.tag(type, jawsJsonPath, untag));
|
||||
});
|
||||
|
||||
return Promise.all(tagQueue);
|
||||
|
||||
@ -329,8 +329,6 @@ exports.getEnvFile = function(awsProfile, awsRegion, bucketName, projectName, st
|
||||
Key: key,
|
||||
};
|
||||
|
||||
utils.logIfVerbose('Getting env file from ' + bucketName + '/' + key);
|
||||
|
||||
return this.getS3Object(awsProfile, awsRegion, params);
|
||||
};
|
||||
|
||||
|
||||
264
lib/utils/cli.js
Normal file
264
lib/utils/cli.js
Normal file
@ -0,0 +1,264 @@
|
||||
// 'use strict';
|
||||
|
||||
/**
|
||||
* JAWS Services: CLI
|
||||
*/
|
||||
|
||||
var Promise = require('bluebird'),
|
||||
prompt = require('prompt'),
|
||||
path = require('path'),
|
||||
os = require('os'),
|
||||
JawsError = require('../jaws-error/index'),
|
||||
utils = require('../utils'),
|
||||
fs = require('fs'),
|
||||
chalk = require('chalk'),
|
||||
Spinner = require('cli-spinner').Spinner,
|
||||
keypress = require('keypress'),
|
||||
packageJson = require('../../package.json');
|
||||
|
||||
Promise.promisifyAll(fs);
|
||||
|
||||
/**
|
||||
* ASCII
|
||||
*/
|
||||
module.exports.ascii = function() {
|
||||
|
||||
var art = '';
|
||||
art = art + ' ____ _____ __ __ _________ ' + os.EOL;
|
||||
art = art + ' | | / _ \\/ \\ / \\/ _____/ ' + os.EOL;
|
||||
art = art + ' | |/ /_\\ \\ \\/\\/ /\\_____ \\ ' + os.EOL;
|
||||
art = art + ' /\\__| / | \\ / / \\ ' + os.EOL;
|
||||
art = art + ' \\________\\____|__ /\\__/\\__/ /_________/ v' + packageJson.version + os.EOL;
|
||||
art = art + '' + os.EOL;
|
||||
art = art + ' *** The Server-Less Framework *** ' + os.EOL;
|
||||
|
||||
console.log(chalk.yellow(art));
|
||||
};
|
||||
|
||||
/**
|
||||
* Spinner
|
||||
*/
|
||||
module.exports.spinner = function(message) {
|
||||
var spinner = new Spinner('JAWS: ' + chalk.yellow('%s ' + message));
|
||||
spinner.setSpinnerString('|/-\\');
|
||||
return spinner;
|
||||
};
|
||||
|
||||
/**
|
||||
* Log
|
||||
*/
|
||||
module.exports.log = function(message) {
|
||||
console.log('JAWS: ' + chalk.yellow(message + ' '));
|
||||
};
|
||||
|
||||
/**
|
||||
* Prompt
|
||||
*/
|
||||
module.exports.prompt = function() {
|
||||
prompt.start();
|
||||
prompt.delimiter = '';
|
||||
prompt.message = 'JAWS: ';
|
||||
return prompt;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prompt: Select
|
||||
*
|
||||
* Accepts array: {key: '1: ', key2: '(deployed) ', value: 'a great choice!'}
|
||||
* Or: {spacer: '-----'}
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
var Select = {
|
||||
data: null,
|
||||
};
|
||||
|
||||
// Render
|
||||
Select._render = function() {
|
||||
|
||||
var _this = this;
|
||||
|
||||
// Clear Rendering
|
||||
_this._clear();
|
||||
|
||||
// Reset line count
|
||||
_this.state.lines = 1;
|
||||
|
||||
// Render Line
|
||||
for (var i = 0; i < _this.state.choices.length; i++) {
|
||||
|
||||
var choice = _this.state.choices[i],
|
||||
line = '';
|
||||
|
||||
// Increment line count
|
||||
_this.state.lines++;
|
||||
|
||||
// Select Arrow
|
||||
var arrow = i === (_this.state.index - 1) ? ' > ' : ' ';
|
||||
|
||||
// Render Choice
|
||||
if (choice.label) {
|
||||
// Line - Key
|
||||
if (choice.key) line = line + choice.key;
|
||||
// Line - Key2
|
||||
if (choice.key2) line = line + choice.key2;
|
||||
// Line - Line
|
||||
line = line + choice.label;
|
||||
// Add toggled style
|
||||
if (choice.toggled) {
|
||||
line = chalk.yellow(line);
|
||||
}
|
||||
// Add line break
|
||||
line = line + os.EOL;
|
||||
}
|
||||
|
||||
// Render Spacer
|
||||
if (choice.spacer) {
|
||||
line = chalk.grey(choice.spacer) + os.EOL;
|
||||
}
|
||||
|
||||
// TODO: Add custom word wrap after measuring terminal width. Re-count lines.
|
||||
|
||||
// Render
|
||||
process.stdout.write(arrow + line);
|
||||
}
|
||||
};
|
||||
|
||||
// Private: Clear Rendering
|
||||
Select._clear = function() {
|
||||
|
||||
var _this = this;
|
||||
|
||||
for (var i = 1; i < Select.state.lines; i++) {
|
||||
process.stdout.moveCursor(0, -1);
|
||||
process.stdout.clearLine();
|
||||
}
|
||||
};
|
||||
|
||||
// Private: Close
|
||||
Select._close = function(cb) {
|
||||
|
||||
var _this = this;
|
||||
|
||||
process.stdin.pause();
|
||||
|
||||
// Gather Choices
|
||||
var selected = [];
|
||||
for (var i = 0; i < _this.state.choices.length; i++) {
|
||||
if (_this.state.choices[i].toggled) selected.push(_this.state.choices[i]);
|
||||
}
|
||||
|
||||
return Select._promise(selected);
|
||||
};
|
||||
|
||||
/**
|
||||
* Select
|
||||
* @param message
|
||||
* @param choices
|
||||
* @param multi
|
||||
* @param spacer
|
||||
* @param doneLabel
|
||||
* @returns {Promise}
|
||||
*/
|
||||
module.exports.select = function(message, choices, multi, doneLabel) {
|
||||
|
||||
// Set keypress listener, if not set
|
||||
if (!Select.state) {
|
||||
|
||||
keypress(process.stdin);
|
||||
|
||||
process.stdin.on('keypress', function (ch, key) {
|
||||
|
||||
if (key && key.ctrl && key.name == 'c') {
|
||||
process.stdin.pause();
|
||||
|
||||
} else if (key.name == 'up' && Select.state.index > 1) {
|
||||
|
||||
if (Select.state.index === 2 && Select.state.choices[0].spacer) {
|
||||
|
||||
// If first choice is spacer, do nothing
|
||||
Select.state.index = 2;
|
||||
} else if (Select.state.choices[Select.state.index - 2].spacer) {
|
||||
|
||||
// If next choice is spacer, move up 2
|
||||
Select.state.index = Select.state.index - 2;
|
||||
} else {
|
||||
|
||||
// Move up
|
||||
Select.state.index = Select.state.index - 1;
|
||||
}
|
||||
|
||||
return Select._render();
|
||||
|
||||
} else if (key.name == 'down' && Select.state.index < Select.state.choices.length) {
|
||||
|
||||
if (Select.state.choices[Select.state.index].spacer) {
|
||||
|
||||
// If next choice is spacer, move down 2
|
||||
Select.state.index = Select.state.index + 2;
|
||||
} else {
|
||||
|
||||
// Move down
|
||||
Select.state.index = Select.state.index + 1;
|
||||
}
|
||||
|
||||
return Select._render();
|
||||
|
||||
} else if (key.name == 'return') {
|
||||
|
||||
// Check if "done" option
|
||||
if (Select.state.choices[Select.state.index - 1].action
|
||||
&& Select.state.choices[Select.state.index - 1].action.toLowerCase() === 'done') {
|
||||
return Select._close();
|
||||
} else {
|
||||
|
||||
// Toggle option
|
||||
Select.state.choices[Select.state.index - 1].toggled = Select.state.choices[Select.state.index - 1].toggled ? false : true;
|
||||
|
||||
if (!Select.state.multi) {
|
||||
Select._close();
|
||||
} else {
|
||||
return Select._render();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.setRawMode(true);
|
||||
}
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
|
||||
// Resume stdin
|
||||
process.stdin.resume();
|
||||
process.stdin.setEncoding('utf8');
|
||||
|
||||
// Update CheckList
|
||||
Select.state = {
|
||||
choices: choices,
|
||||
index: (choices[0] && choices[0].spacer) ? 2 : 1,
|
||||
lines: 0,
|
||||
multi: multi,
|
||||
doneLabel: doneLabel ? doneLabel : 'Done',
|
||||
};
|
||||
|
||||
// Add Done and Cancel to choices
|
||||
if (Select.state.multi) {
|
||||
Select.state.choices.push(
|
||||
{ spacer: '- - - - -' },
|
||||
{
|
||||
action: 'Done',
|
||||
label: Select.state.doneLabel,
|
||||
});
|
||||
}
|
||||
|
||||
// Log Message
|
||||
if (message) console.log('JAWS: ' + chalk.yellow(message));
|
||||
|
||||
// Assign CheckList Promise
|
||||
Select._promise = resolve;
|
||||
|
||||
// Initial Render
|
||||
Select._render();
|
||||
});
|
||||
};
|
||||
@ -211,7 +211,7 @@ module.exports.checkForDuplicateLambdaNames = function(projectRootPath) {
|
||||
|
||||
return this.findAllLambdas(projectRootPath)
|
||||
.then(function(lambdaJawsPaths) {
|
||||
//Verify 2 lambdas dont have same name
|
||||
// Verify 2 lambdas dont have same name
|
||||
lambdaJawsPaths.forEach(function(ljp) {
|
||||
var ljpJson = require(ljp);
|
||||
|
||||
|
||||
@ -46,10 +46,13 @@
|
||||
"inquirer": "^0.9.0",
|
||||
"insert-module-globals": "^6.5.2",
|
||||
"jaws-api-gateway-client": "0.11.0",
|
||||
"keypress": "^0.2.1",
|
||||
"minimist": "^1.2.0",
|
||||
"mkdirp-then": "^1.1.0",
|
||||
"moment": "^2.10.6",
|
||||
"node-uuid": "^1.4.2",
|
||||
"node-zip": "^1.1.0",
|
||||
"prompt": "^0.2.14",
|
||||
"readdirp": "^1.4.0",
|
||||
"shortid": "^2.2.2",
|
||||
"uglify-js": "^2.4.24",
|
||||
|
||||
19
tests/all.js
19
tests/all.js
@ -5,24 +5,25 @@
|
||||
require('./config'); //init config
|
||||
|
||||
describe('AllTests', function() {
|
||||
|
||||
before(function(done) {
|
||||
this.timeout(0); //dont timeout anything
|
||||
done();
|
||||
});
|
||||
|
||||
after(function() {
|
||||
});
|
||||
after(function() {});
|
||||
|
||||
//require tests vs inline so we can run sequentially
|
||||
require('./cli/tag');
|
||||
require('./cli/install');
|
||||
require('./cli/env');
|
||||
require('./cli/generate');
|
||||
//require('./cli/tag');
|
||||
//require('./cli/install');
|
||||
//require('./cli/env');
|
||||
//require('./cli/generate');
|
||||
|
||||
/**
|
||||
* Tests below create AWS Resources
|
||||
*/
|
||||
//require('./cli/dash');
|
||||
//require('./cli/deploy_lambda');
|
||||
//require('./cli/deploy_api');
|
||||
//require('./cli/new'); //Must be run last
|
||||
});
|
||||
//require('./cli/deploy_endpoint');
|
||||
require('./cli/new_project');
|
||||
});
|
||||
73
tests/cli/dash.js
Normal file
73
tests/cli/dash.js
Normal file
@ -0,0 +1,73 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* JAWS Test: Dash Command
|
||||
*/
|
||||
|
||||
var Jaws = require('../../lib/index.js'),
|
||||
CMDdash = require('../../lib/commands/dash'),
|
||||
CMDtag = require('../../lib/commands/tag'),
|
||||
JawsError = require('../../lib/jaws-error'),
|
||||
testUtils = require('../test_utils'),
|
||||
Promise = require('bluebird'),
|
||||
path = require('path'),
|
||||
assert = require('chai').assert;
|
||||
|
||||
var config = require('../config'),
|
||||
projPath,
|
||||
JAWS;
|
||||
|
||||
describe('Test "dash" command', function() {
|
||||
|
||||
before(function(done) {
|
||||
this.timeout(0);
|
||||
|
||||
// Tag All Lambdas & Endpoints
|
||||
return Promise.try(function() {
|
||||
|
||||
// Create Test Project
|
||||
projPath = testUtils.createTestProject(
|
||||
config.name,
|
||||
config.region,
|
||||
config.stage,
|
||||
config.iamRoleArnLambda,
|
||||
config.iamRoleArnApiGateway,
|
||||
config.envBucket,
|
||||
['back']);
|
||||
process.chdir(path.join(projPath, 'back'));
|
||||
|
||||
// Instantiate JAWS
|
||||
JAWS = new Jaws();
|
||||
})
|
||||
.then(function() {
|
||||
return CMDtag.tagAll(JAWS, 'lambda');
|
||||
})
|
||||
.then(function() {
|
||||
return CMDtag.tagAll(JAWS, 'endpoint');
|
||||
})
|
||||
.then(function() {
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
after(function(done) {
|
||||
done();
|
||||
});
|
||||
|
||||
describe('Positive tests', function() {
|
||||
it('Dash deployment via tagged resources', function(done) {
|
||||
this.timeout(0);
|
||||
|
||||
CMDdash.run(JAWS, config.stage, [config.region], true)
|
||||
.then(function() {
|
||||
done();
|
||||
})
|
||||
.catch(JawsError, function(e) {
|
||||
done(e);
|
||||
})
|
||||
.error(function(e) {
|
||||
done(e);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -46,7 +46,7 @@ describe('Test deploy api command', function() {
|
||||
|
||||
this.timeout(0);
|
||||
|
||||
theCmd.deployApi(JAWS, config.stage, config.region, true)
|
||||
theCmd.run(JAWS, config.stage, config.region, true)
|
||||
.then(function() {
|
||||
done();
|
||||
})
|
||||
@ -42,9 +42,9 @@ describe('Test "deploy lambda" command', function() {
|
||||
it('Multi level module deploy', function(done) {
|
||||
this.timeout(0);
|
||||
|
||||
process.chdir(path.join(projPath, 'back/lambdas/users/show'));
|
||||
process.chdir(path.join(projPath, 'back/lambdas/sessions/show'));
|
||||
|
||||
theCmd.deployLambdas(JAWS, config.stage, false, false)
|
||||
theCmd.run(JAWS, config.stage, false, false)
|
||||
.then(function(d) {
|
||||
done();
|
||||
})
|
||||
@ -57,7 +57,7 @@ describe('Test "deploy lambda" command', function() {
|
||||
this.timeout(0);
|
||||
process.chdir(path.join(projPath, 'back/lambdas/bundle/browserify'));
|
||||
|
||||
theCmd.deployLambdas(JAWS, config.stage, false, false)
|
||||
theCmd.run(JAWS, config.stage, false, false)
|
||||
.then(function(d) {
|
||||
done();
|
||||
})
|
||||
@ -70,7 +70,7 @@ describe('Test "deploy lambda" command', function() {
|
||||
this.timeout(0);
|
||||
process.chdir(path.join(projPath, 'back/lambdas/bundle/nonoptimized'));
|
||||
|
||||
theCmd.deployLambdas(JAWS, config.stage, false, false)
|
||||
theCmd.run(JAWS, config.stage, false, false)
|
||||
.then(function(d) {
|
||||
done();
|
||||
})
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
* - Deletes the CF stack created by the project
|
||||
*/
|
||||
var Jaws = require('../../lib/index.js'),
|
||||
JawsError = require('../../lib/jaws-error'),
|
||||
theCmd = require('../../lib/commands/new_project'),
|
||||
path = require('path'),
|
||||
os = require('os'),
|
||||
@ -31,17 +32,24 @@ describe('Test new command', function() {
|
||||
|
||||
this.timeout(0);
|
||||
|
||||
theCmd.create(
|
||||
theCmd.run(
|
||||
config.newName,
|
||||
config.stage,
|
||||
config.envBucket,
|
||||
config.region,
|
||||
config.notifyEmail,
|
||||
config.profile
|
||||
)
|
||||
config.region,
|
||||
config.profile)
|
||||
.then(function() {
|
||||
var jawsJson = require(path.join(os.tmpdir(), config.newName, 'jaws.json'));
|
||||
assert.isTrue(!!jawsJson.project.regions['us-east-1'].stages[config.stage].iamRoleArn);
|
||||
var region = false;
|
||||
|
||||
for (var i = 0; i < jawsJson.project.stages[config.stage].length; i++) {
|
||||
var stage = jawsJson.project.stages[config.stage][i];
|
||||
if (stage.region === config.region) {
|
||||
region = stage.region;
|
||||
}
|
||||
}
|
||||
assert.isTrue(region !== false);
|
||||
done();
|
||||
})
|
||||
.catch(JawsError, function(e) {
|
||||
@ -53,12 +61,6 @@ describe('Test new command', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error tests', function() {
|
||||
it('Create new project', function(done) {
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
//it('Delete Cloudformation stack from new project', function(done) {
|
||||
// this.timeout(0);
|
||||
// var CF = new config.AWS.CloudFormation();
|
||||
@ -67,4 +69,4 @@ describe('Test new command', function() {
|
||||
// done();
|
||||
// });
|
||||
//});
|
||||
});
|
||||
});
|
||||
@ -12,7 +12,7 @@ var AWS = require('aws-sdk'),
|
||||
uuid = require('node-uuid'),
|
||||
Promise = require('bluebird');
|
||||
|
||||
module.exports.run = function(event, context) {
|
||||
module.exports.handler = function(event, context) {
|
||||
console.log('about to run');
|
||||
|
||||
var s3 = Promise.promisifyAll(new AWS.S3());
|
||||
@ -8,7 +8,7 @@
|
||||
"functionName": "browserifytest",
|
||||
"runtime": "nodejs",
|
||||
"runtimeVer": "0.10.36",
|
||||
"handler": "lambdas/bundle/browserify/main.run",
|
||||
"handler": "lambdas/bundle/browserify/index.handler",
|
||||
"envVars": [
|
||||
"MYAPP_SERVICE_KEY",
|
||||
"MYAPP_SERVICE2_KEY"
|
||||
|
||||
@ -13,7 +13,7 @@ var AWS = require('aws-sdk'),
|
||||
Promise = require('bluebird'),
|
||||
awsMetadata = require('aws-sdk/package.json');
|
||||
|
||||
module.exports.run = function(event, context) {
|
||||
module.exports.handler = function(event, context) {
|
||||
console.log('AWS sdk version', awsMetadata.version);
|
||||
|
||||
var s3 = Promise.promisifyAll(new AWS.S3());
|
||||
@ -8,7 +8,7 @@
|
||||
"functionName": "notoptimizedtest",
|
||||
"runtime": "nodejs",
|
||||
"runtimeVer": "0.10.36",
|
||||
"handler": "lambdas/bundle/nonoptimized/main.run",
|
||||
"handler": "lambdas/bundle/nonoptimized/index.handler",
|
||||
"envVars": [
|
||||
"MYAPP_SERVICE_KEY",
|
||||
"MYAPP_SERVICE2_KEY"
|
||||
|
||||
7
tests/test-prj/back/lambdas/sessions/create/index.js
Normal file
7
tests/test-prj/back/lambdas/sessions/create/index.js
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* API: Sessions: Create
|
||||
*/
|
||||
|
||||
exports.handler = function(event, context) {
|
||||
context.done(null, { message: 'This test lambda function has run successfully!' });
|
||||
};
|
||||
@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "jaws-users-signin",
|
||||
"name": "jaws-sessions-create",
|
||||
"version": "0.0.1",
|
||||
"location": "https://github.com/jaws-stack/jaws-users-crud-ddb-jwt-js",
|
||||
"author": "JAWS",
|
||||
"description": "A group of lambda functions for user crud operations using dynamodb, JSON web tokens and javascript",
|
||||
"lambda": {
|
||||
"functionName": "usersSignIn",
|
||||
"functionName": "sessionsCreate",
|
||||
"runtime": "nodejs",
|
||||
"runtimeVer": "0.10.36",
|
||||
"handler": "lambdas/users/signin/index.handler",
|
||||
"handler": "lambdas/sessions/create/index.handler",
|
||||
"envVars": [
|
||||
"MYAPP_SERVICE_KEY",
|
||||
"MYAPP_SERVICE2_KEY"
|
||||
@ -28,9 +28,9 @@
|
||||
}
|
||||
},
|
||||
"endpoint": {
|
||||
"type": "lambda",
|
||||
"path": "sessions/{sessionId}",
|
||||
"method": "PUT",
|
||||
"type": "AWS",
|
||||
"path": "sessions",
|
||||
"method": "POST",
|
||||
"authorizationType": "none",
|
||||
"apiKeyRequired": false,
|
||||
"requestTemplates": {
|
||||
7
tests/test-prj/back/lambdas/sessions/show/index.js
Normal file
7
tests/test-prj/back/lambdas/sessions/show/index.js
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* API: Sessions: Show
|
||||
*/
|
||||
|
||||
exports.handler = function(event, context) {
|
||||
context.done(null, { message: 'This test lambda function has run successfully!' });
|
||||
};
|
||||
@ -5,10 +5,10 @@
|
||||
"author": "JAWS",
|
||||
"description": "A lambda function to fetch a user from the database and show them",
|
||||
"lambda": {
|
||||
"functionName": "usersShow",
|
||||
"functionName": "sessionsShow",
|
||||
"runtime": "nodejs",
|
||||
"runtimeVer": "0.10.33",
|
||||
"handler": "lambdas/users/show/index.handler",
|
||||
"handler": "lambdas/sessions/show/index.handler",
|
||||
"envVars": [
|
||||
"MYAPP_SERVICE_KEY",
|
||||
"MYAPP_SERVICE2_KEY"
|
||||
@ -28,7 +28,7 @@
|
||||
}
|
||||
},
|
||||
"endpoint": {
|
||||
"type": "lambda",
|
||||
"type": "AWS",
|
||||
"path": "sessions/{sessionId}",
|
||||
"method": "GET",
|
||||
"authorizationType": "none",
|
||||
7
tests/test-prj/back/lambdas/users/create/index.js
Normal file
7
tests/test-prj/back/lambdas/users/create/index.js
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* API: Users: Create
|
||||
*/
|
||||
|
||||
exports.handler = function(event, context) {
|
||||
context.done(null, { message: 'This test lambda function has run successfully!' });
|
||||
};
|
||||
@ -5,10 +5,10 @@
|
||||
"author": "JAWS",
|
||||
"description": "A group of lambda functions for user crud operations using dynamodb, JSON web tokens and javascript",
|
||||
"lambda": {
|
||||
"functionName": "usersSignUp",
|
||||
"functionName": "usersCreate",
|
||||
"runtime": "nodejs",
|
||||
"runtimeVer": "0.10.36",
|
||||
"handler": "lambdas/users/signup/index.handler",
|
||||
"handler": "lambdas/users/create/index.handler",
|
||||
"envVars": [
|
||||
"MYAPP_SERVICE_KEY",
|
||||
"MYAPP_SERVICE2_KEY"
|
||||
@ -28,7 +28,7 @@
|
||||
}
|
||||
},
|
||||
"endpoint": {
|
||||
"type": "lambda",
|
||||
"type": "AWS",
|
||||
"path": "users",
|
||||
"method": "POST",
|
||||
"authorizationType": "none",
|
||||
@ -1,9 +0,0 @@
|
||||
/**
|
||||
* API: Users: Show
|
||||
*/
|
||||
|
||||
exports.handler = function(event, context) {
|
||||
|
||||
context.done(null, { message: 'You\'ve made a successful request to your JAWS API!' });
|
||||
|
||||
};
|
||||
@ -1,5 +0,0 @@
|
||||
/**
|
||||
* API: Users: Sign-In
|
||||
*/
|
||||
|
||||
exports.handler = function(event, context) {};
|
||||
@ -1,5 +0,0 @@
|
||||
/**
|
||||
* API: Users: Sign-Up
|
||||
*/
|
||||
|
||||
exports.handler = function(event, context) {};
|
||||
@ -61,7 +61,7 @@ module.exports.createTestProject = function(projectName,
|
||||
projectJSON.project.stages[projectStage] = [{
|
||||
region: projectRegion,
|
||||
iamRoleArnLambda: projectLambdaIAMRole,
|
||||
iamRoleArnApiGateway: projectApiGIAMRole
|
||||
iamRoleArnApiGateway: projectApiGIAMRole,
|
||||
},];
|
||||
projectJSON.project.envVarBucket = {
|
||||
name: projectEnvBucket,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user