create awd profile files if DNE. dont use dep fs.exists

This commit is contained in:
doapp-ryanp 2015-09-16 09:43:50 -05:00
parent 833b764891
commit 488ec8db6c
21 changed files with 104 additions and 76 deletions

View File

@ -61,7 +61,6 @@ program
));
} else if (type === 'action') {
var action = {};
if (args.l || args.lambda) {
@ -75,8 +74,7 @@ program
}
if (args._.length !== 3) {
throw new JawsError('Please specify the resource and action in this command, like: '
+ '"jaws new action users create".');
throw new JawsError('Please specify the resource and action. Ex: "jaws new action users create"');
}
action.resource = args._[1];
@ -118,7 +116,7 @@ program
program
.command('tag [type]')
.description('Tag lambda function or api gateway resource (endpoint) for deployment ' +
'the next time deploy command is run. Type "lambda" is the default.')
'the next time deploy command is run. Type "lambda" is the default.')
.option('-u, --untag', 'un-tag lambda|endpoint')
.option('-a, --tag-all', 'tag all lambda|endpoint functions in project')
.option('-l, --list-all', 'list all tagged lambda|endpoint functions in project')
@ -155,7 +153,7 @@ program
program
.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')
' 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('-d, --no-cf', 'Don\'t execute the lambda cloudformation, just generate it. Zips will be uploaded to s3')
.action(function(type, stage, region, options) {

View File

@ -6,7 +6,7 @@ This is the scaffolding jaws-cli produces on the new command. Its bare becau
* back
* [.env](./commands.md#env)
* **lambdas**
* **aws_modules**
* **users**
* **create**
* jaws.json

View File

@ -24,9 +24,9 @@ Creates a new stage in existing region. By default executes CloudFormation to m
##### type `action`
Creates one or both of the following:
Creates one or both of the following in the `back/aws_modules` folder:
* A lambda function in the `lambdas/back` folder with basic scaffolding.
* A lambda function with basic skeleton
* An API gateway configuration
### jaws dash
@ -65,7 +65,7 @@ When deploying a Lambda function to AWS, JAWS will:
The `jaws install` command downloads the JAWS-module from the location specified (a github repo) and installs it. The install includes:
* If the `--save` flag was used and if `cfExtensions` CloudFormation template was included in the modules [`jaws.json`](./jaws-json.md), it merges the contents into the projects [`jaws-cf.json`](./jaws-cf-json.md). You will have to manually divide this up into multiple CF templates afterwards, if thats your preference.
* Copies the jaws-module into the `back/lambdas` dir of the project you are currently in
* Copies the jaws-module into the `back/aws_modules` dir of the project you are currently in
### jaws log

View File

@ -2,7 +2,7 @@
The `jaws.json` file contains configuration details for the included code and authorship details for easy publishing. This is similar to `package.json` but for jaws-modules. `jaws.json` files exist at a few different levels in a JAWS proejct:
* **Project**: lives at the root of your project. Defines things like stages. [example here](../examples/project-jaws.json)
* **`lambdas` directory**: `jaws.json` exists for every lambda function. It defines things like memory size and api gateway endpoint configuration. [example here](../examples/lambda-jaws.json)
* **`aws_modules` directory**: `jaws.json` exists for every lambda function. It defines things like memory size and api gateway endpoint configuration. [example here](../examples/lambda-jaws.json)
* **JAWS plug-in module**: lives at the root of the hosted project
## Common jaws.json attributes
@ -43,9 +43,9 @@ See lambda `jaws.json` [example here](../examples/lambda-jaws.json)
* `includePaths`: Paths rel to back (dirs or files) to be included in zip. Paths included after optimization step.
* `excludePatterns`: Array of regular expressions rel to back. Removed before optimization step. If not optimizing, everything in back dir will be included in zip. Use this to exclude stuff you don't want in your zip. Strings will be passed to `new RegExp()`
For an optimize example using the most popular node modules see [browserify tests](../tests/test-prj/back/lambdas/bundle/browserify)
For an optimize example using the most popular node modules see [browserify tests](../tests/test-prj/back/aws_modules/bundle/browserify)
For non optimize example see [non optimized tests](../tests/test-prj/back/lambdas/bundle/nonoptimized)
For non optimize example see [non optimized tests](../tests/test-prj/back/aws_modules/bundle/nonoptimized)
##### API Gateway (`endpoint`) attributes:

View File

@ -24,7 +24,7 @@
},
"cloudFormation": {
"Description": "",
"Handler": "lambdas/users/create/index.handler",
"Handler": "aws_modules/users/create/index.handler",
"MemorySize": 1024,
"Runtime": "nodejs",
"Timeout": 6

View File

@ -196,7 +196,7 @@ Deployer.prototype.deploy = Promise.method(function() {
awsmLambdas = {};
return Promise.try(function() {
})
})
.bind(_this)
.then(function() {
return _this._lambdaAwsmPaths;
@ -216,14 +216,14 @@ Deployer.prototype.deploy = Promise.method(function() {
JawsCLI.log("Lambda Deployer: uploading " + packagedLambda.lambdaName);
return AWSUtils.putLambdaZip(
_this._JAWS._meta._profile,
_this._region,
jawsBucket,
projName,
_this._stage,
packagedLambda.lambdaName,
packagedLambda.zipBuffer
)
_this._JAWS._meta._profile,
_this._region,
jawsBucket,
projName,
_this._stage,
packagedLambda.lambdaName,
packagedLambda.zipBuffer
)
.then(function(s3Key) {
awsmLambdas[lambdaAwsmPath] = {
Code: {
@ -290,11 +290,10 @@ Deployer.prototype._generateLambdaCf = function(taggedLambdaPkgs) {
//TODO: docs: if someone manually changes resource or action dir names and does NOT mark the changed awsm.jsons
//for deploy they will lose a lambda
var _this = this,
existingStack = true;
existingStack = true,
projName = _this._JAWS._meta.projectJson.name;
return AWSUtils.cfGetLambdasStackTemplate(
_this.JAWS._meta.profile, _this._region, _this._stage, _this._JAWS._meta.projectJson.name
)
return AWSUtils.cfGetLambdasStackTemplate(_this.JAWS._meta.profile, _this._region, _this._stage, projName)
.error(function(e) {
if (e && e.code !== 'ResourceNotFoundException') {
console.error(
@ -335,6 +334,7 @@ Deployer.prototype._generateLambdaCf = function(taggedLambdaPkgs) {
});
}
lambdaCfTemplate.Description = projName + " lambdas";
return lambdaCfTemplate;
})
.then(function(lambdaCfTemplate) {

View File

@ -102,9 +102,9 @@ function _installFiles(url, rootPath) {
if (['lambda', 'lambdaGroup'].indexOf(jawsJson.profile) > -1) {
// If folder exists, create unique module folder name
if (fs.existsSync(modulePath)) {
if (utils.dirExistsSync(modulePath)) {
for (var i = 2; i < 500; i++) {
if (!fs.existsSync(modulePath + '-' + i)) {
if (!utils.dirExistsSync(modulePath + '-' + i)) {
jawsJson.name = jawsJson.name + '-' + i;
modulePath = path.join(rootPath, 'back', jawsJson.name);
break;

View File

@ -25,7 +25,7 @@ module.exports.run = function(JAWS, action) {
};
/**
* CMD Class
* CMD Classlam
*/
function CMD(JAWS, action) {
@ -102,7 +102,7 @@ CMD.prototype._createSkeleton = Promise.method(function() {
_this._action.resource,
_this._action.action);
if (fs.existsSync(actionPath)) {
if (utils.dirExistsSync(actionPath)) {
throw new JawsError(
actionPath + ' already exists',
JawsError.errorCodes.INVALID_PROJECT_JAWS
@ -139,7 +139,7 @@ CMD.prototype._createSkeleton = Promise.method(function() {
// Make package.json, if it doesn't exist already
var packageJsonPath = path.join(_this._JAWS._meta.projectRootPath, 'back', 'package.json');
var packageJson = JSON.parse(fs.readFileSync(path.join(templatesPath, 'nodejs', 'package.json')));
if (!fs.existsSync(packageJsonPath)) {
if (!utils.fileExistsSync(packageJsonPath)) {
utils.logIfVerbose('creating package.json since it does not exist');
writeFilesDeferred.push(
utils.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2))
@ -148,8 +148,8 @@ CMD.prototype._createSkeleton = Promise.method(function() {
// Copy over dotenv if it doesn't already exist
var nodeModulesPath = path.join(_this._JAWS._meta.projectRootPath, 'back', 'node_modules');
if (!fs.existsSync(path.join(nodeModulesPath, 'dotenv'))) {
if (!fs.existsSync(nodeModulesPath)) {
if (!utils.dirExistsSync(path.join(nodeModulesPath, 'dotenv'))) {
if (!utils.dirExistsSync(nodeModulesPath)) {
fs.mkdirSync(nodeModulesPath);
}
wrench.copyDirSyncRecursive(path.resolve(__dirname, '..', '..', 'node_modules', 'dotenv'),

View File

@ -83,10 +83,10 @@ CMD.prototype.run = Promise.method(function() {
return Promise.try(function() {
// ASCII Greeting
JawsCLI.ascii();
// ASCII Greeting
JawsCLI.ascii();
})
})
.bind(_this)
.then(_this._prompt)
.then(_this._prepareProjectData)
@ -94,8 +94,8 @@ CMD.prototype.run = Promise.method(function() {
.then(_this._createProjectDirectory)
.then(function() {
if (_this._noCf) {
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('!!MAKE SURE!! to create stack with name: ' + AWSUtils.cfGetResourcesStackName(_this._stage, _this._name));
JawsCLI.log('After creating CF stack, remember to put the IAM role outputs in your project jaws.json');
return false;
} else {
@ -169,7 +169,7 @@ CMD.prototype._prompt = Promise.method(function() {
};
// Prompt: API Keys - Create an AWS profile by entering API keys
if (!fs.existsSync(path.join(AWSUtils.getConfigDir(), 'credentials'))) {
if (!utils.fileExistsSync(path.join(AWSUtils.getConfigDir(), 'credentials'))) {
_this.Prompter.override.awsAdminKeyId = _this._awsAdminKeyId;
_this._prompts.properties.awsAdminKeyId = {
@ -278,7 +278,7 @@ CMD.prototype._prepareProjectData = Promise.method(function() {
}
// Append unique id if name is in use
if (fs.existsSync(path.join(process.cwd(), _this._name))) {
if (utils.dirExistsSync(path.join(process.cwd(), _this._name))) {
_this._name = _this._name + '-' + shortid.generate().replace(/\W+/g, '').substring(0, 19);
}
@ -325,14 +325,15 @@ CMD.prototype._createProjectDirectory = Promise.method(function() {
cfTemplate.Parameters.aaStage.Default = _this._stage;
cfTemplate.Parameters.aaDataModelPrefix.Default = _this._stage; //to simplify bootstrap use same stage
cfTemplate.Parameters.aaNotficationEmail.Default = _this._notificationEmail;
cfTemplate.Description = _this._name + " resources";
// Create Project Scaffolding
return utils.writeFile(
path.join(_this._projectRootPath, 'back', '.env'),
'JAWS_STAGE=' + _this._stage
+ '\nJAWS_DATA_MODEL_PREFIX=' + _this._stage
+ '\nJAWS_REGION=' + _this._region
)
path.join(_this._projectRootPath, 'back', '.env'),
'JAWS_STAGE=' + _this._stage
+ '\nJAWS_DATA_MODEL_PREFIX=' + _this._stage
+ '\nJAWS_REGION=' + _this._region
)
.then(function() {
return Promise.all([
fs.mkdirAsync(path.join(_this._projectRootPath, 'front')),
@ -392,13 +393,13 @@ CMD.prototype._createCfStack = Promise.method(function() {
// Create CF stack
return AWSUtils.cfCreateResourcesStack(
_this._profile,
_this._region,
_this._projectRootPath,
_this._name,
_this._stage,
_this._s3Bucket,
_this._notificationEmail)
_this._profile,
_this._region,
_this._projectRootPath,
_this._name,
_this._stage,
_this._s3Bucket,
_this._notificationEmail)
.then(function(cfData) {
return AWSUtils.monitorCf(cfData, _this._profile, _this._region, 'create');
});
@ -413,7 +414,6 @@ CMD.prototype._createCfStack = Promise.method(function() {
*/
CMD.prototype._createProjectJson = Promise.method(function(cfData) {
var _this = this,
iamRoleArnLambda,
iamRoleArnApiGateway;
@ -433,11 +433,11 @@ CMD.prototype._createProjectJson = Promise.method(function(cfData) {
var templatesPath = path.join(__dirname, '..', 'templates'),
jawsJson = JSON.parse(fs.readFileSync(path.join(templatesPath, 'jaws.json')));
jawsJson.stages[_this._stage] = {
jawsJson.stages[_this._stage] = [{
region: _this._region,
iamRoleArnLambda: iamRoleArnLambda || '',
iamRoleArnApiGateway: iamRoleArnApiGateway || '',
};
}];
jawsJson.jawsBuckets[_this._region] = _this._s3Bucket;

View File

@ -28,7 +28,7 @@ module.exports.tag = function(type, fullPathToAwsmJson, untag) {
var awsmJson = require(awsmJsonPath);
return new Promise(function(resolve, reject) {
if (!fs.existsSync(awsmJsonPath)) {
if (!utils.fileExistsSync(awsmJsonPath)) {
reject(new JawsError('Could\'nt find a valid awsm.json. Sure you are in the correct directory?'));
}

View File

@ -47,7 +47,7 @@ Jaws.prototype.validateProject = Promise.method(function() {
throw new JawsError('Must be in a JAWS project', JawsError.errorCodes.NOT_IN_JAWS_PROJECT);
}
if (!_this._meta.projectJson || !_this._meta.projectJson.project || !_this._meta.projectJson.stages) {
if (!_this._meta.projectJson || !_this._meta.projectJson.stages) {
throw new JawsError(
'JAWS project must have at least one stage and region defined',
JawsError.errorCodes.INVALID_PROJECT_JAWS

View File

@ -77,8 +77,17 @@ module.exports.profilesMap = function() {
* @param secretKey
*/
module.exports.profilesSet = function(awsProfile, awsRegion, accessKeyId, secretKey) {
var credsPath = path.join(this.getConfigDir(), 'credentials'),
configPath = path.join(path.dirname(credsPath), 'config');
if (!utils.fileExistsSync(credsPath)) {
utils.writeFile(credsPath);
}
if (!utils.fileExistsSync(configPath)) {
utils.writeFile(configPath);
}
var credsPath = path.join(this.getConfigDir(), 'credentials');
fs.appendFileSync(
credsPath,
'[' + awsProfile + ']' + os.EOL +
@ -88,7 +97,7 @@ module.exports.profilesSet = function(awsProfile, awsRegion, accessKeyId, secret
var profileNameForConfig = (awsProfile == 'default') ? 'default' : 'profile ' + awsProfile;
fs.appendFileSync(
path.join(path.dirname(credsPath), 'config'),
configPath,
'[' + profileNameForConfig + ']' + os.EOL +
'region = ' + awsRegion + os.EOL);
};
@ -173,8 +182,8 @@ exports.cfGetLambdasStackTemplate = function(awsProfile, awsRegion, stage, projN
}));
return CF.getTemplateAsync({
StackName: _this.cfGetLambdasStackName(stage, projName)
})
StackName: _this.cfGetLambdasStackName(stage, projName)
})
.then(function(data) {
return data.TemplateBody;
});

View File

@ -65,11 +65,12 @@ module.exports.findAllAwsmPathsOfType = function(projectRootPath, type) {
* @returns {*}
*/
module.exports.findProjectRootPath = function(startDir) {
var _this = this;
// Check if startDir is root
if (fs.existsSync(path.join(startDir, 'jaws.json'))) {
if (_this.fileExistsSync(path.join(startDir, 'jaws.json'))) {
var jawsJsonInDir = require(path.join(startDir, 'jaws.json'));
if (typeof jawsJsonInDir.project !== 'undefined') return path.resolve(startDir);
if (typeof jawsJsonInDir.name !== 'undefined') return path.resolve(startDir);
}
// Check up to 10 parent levels
@ -80,9 +81,9 @@ module.exports.findProjectRootPath = function(startDir) {
previous = path.join(previous, '../');
var fullPath = path.resolve(startDir, previous);
if (fs.existsSync(path.join(fullPath, 'jaws.json'))) {
if (_this.fileExistsSync(path.join(fullPath, 'jaws.json'))) {
var jawsJson = require(path.join(fullPath, 'jaws.json'));
if (typeof jawsJson.project !== 'undefined') {
if (typeof jawsJson.name !== 'undefined') {
projRootPath = fullPath;
break;
}
@ -263,3 +264,23 @@ module.exports.getProjRegionConfigForStage = function(projectJawsJson, stage, re
return region[0];
};
module.exports.dirExistsSync = function(path) {
try {
var stats = fs.lstatSync(path);
return stats.isDirectory();
}
catch (e) {
return false;
}
};
module.exports.fileExistsSync = function(path) {
try {
var stats = fs.lstatSync(path);
return stats.isFile();
}
catch (e) {
return false;
}
};

View File

@ -28,7 +28,7 @@ describe('Test deploy endpoint command', function() {
config.iamRoleArnLambda,
config.iamRoleArnApiGateway,
config.envBucket);
process.chdir(path.join(projPath, 'back/lambdas/sessions/show'));
process.chdir(path.join(projPath, 'back/aws_modules/sessions/show'));
JAWS = new Jaws();
// Get Lambda Paths

View File

@ -38,7 +38,7 @@ describe('Test "deploy lambda" command', function() {
it('Multi level module deploy', function(done) {
this.timeout(0);
process.chdir(path.join(projPath, 'back/lambdas/sessions/show'));
process.chdir(path.join(projPath, 'back/aws_modules/sessions/show'));
CmdDeployLambda.run(JAWS, config.stage, [config.region], false)
.then(function(d) {
@ -51,7 +51,7 @@ describe('Test "deploy lambda" command', function() {
it('browserify deploy', function(done) {
this.timeout(0);
process.chdir(path.join(projPath, 'back/lambdas/bundle/browserify'));
process.chdir(path.join(projPath, 'back/aws_modules/bundle/browserify'));
CmdDeployLambda.run(JAWS, config.stage, [config.region], false)
.then(function(d) {
@ -64,7 +64,7 @@ describe('Test "deploy lambda" command', function() {
it('non optimized deploy', function(done) {
this.timeout(0);
process.chdir(path.join(projPath, 'back/lambdas/bundle/nonoptimized'));
process.chdir(path.join(projPath, 'back/aws_modules/bundle/nonoptimized'));
CmdDeployLambda.run(JAWS, config.stage, [config.region], false)
.then(function(d) {

View File

@ -52,7 +52,7 @@ describe('Test "new action" command', function() {
CmdNewAction.run(JAWS, action)
.then(function() {
var jawsJson = require(path.join(process.cwd(), 'lambdas/users/list/awsm.json'));
var jawsJson = require(path.join(process.cwd(), 'aws_modules/users/list/awsm.json'));
assert.isTrue(typeof jawsJson.lambda.cloudFormation !== 'undefined');
assert.isTrue(typeof jawsJson.apiGateway.cloudFormation !== 'undefined');
assert.isTrue(jawsJson.apiGateway.cloudFormation.Path === 'users/list');

View File

@ -24,7 +24,7 @@
},
"cloudFormation": {
"Description": "",
"Handler": "lambdas/bundle/browserify/index.handler",
"Handler": "aws_modules/bundle/browserify/index.handler",
"MemorySize": 1024,
"Runtime": "nodejs",
"Timeout": 6

View File

@ -20,13 +20,13 @@
"includePaths": []
},
"excludePatterns": [
"lambdas/[u].*",
"lambdas/bundle/b.*"
"aws_modules/[u].*",
"aws_modules/bundle/b.*"
]
},
"cloudFormation": {
"Description": "",
"Handler": "lambdas/bundle/nonoptimized/index.handler",
"Handler": "aws_modules/bundle/nonoptimized/index.handler",
"MemorySize": 1024,
"Runtime": "nodejs",
"Timeout": 6

View File

@ -24,7 +24,7 @@
},
"cloudFormation": {
"Description": "",
"Handler": "lambdas/sessions/create/index.handler",
"Handler": "aws_modules/sessions/create/index.handler",
"MemorySize": 1024,
"Runtime": "nodejs",
"Timeout": 6

View File

@ -24,7 +24,7 @@
},
"cloudFormation": {
"Description": "",
"Handler": "lambdas/sessions/show/index.handler",
"Handler": "aws_modules/sessions/show/index.handler",
"MemorySize": 1024,
"Runtime": "nodejs",
"Timeout": 6

View File

@ -24,7 +24,7 @@
},
"cloudFormation": {
"Description": "",
"Handler": "lambdas/users/create/index.handler",
"Handler": "aws_modules/users/create/index.handler",
"MemorySize": 1024,
"Runtime": "nodejs",
"Timeout": 6