use aws_modules

This commit is contained in:
doapp-ryanp 2015-09-15 21:28:00 -05:00
parent a14480e47a
commit f508846b96
10 changed files with 200 additions and 117 deletions

View File

@ -67,13 +67,13 @@ function CMD(JAWS, stage, region, allTagged, noExeCf) {
/**
* CMD: Run
*
* @returns {Promise} map of lambdaAwsmPaths to {Code:{},lambdaName:""}
*/
CMD.prototype.run = Promise.method(function() {
var _this = this;
// Flow
return _this._JAWS.validateProject()
.bind(_this)
.then(_this._promptStage)
@ -85,8 +85,9 @@ CMD.prototype.run = Promise.method(function() {
.each(function(region) {
var deployer = new Deployer(_this._JAWS, _this._lambdaAwsmPaths, _this._stage, region, _this._noExeCf);
return deployer.deploy();
}).then(function() {
}).then(function(lambdaAwsmPkgs) {
JawsCLI.log('Lambda Deployer: Successfully deployed lambdas to the requested regions!');
return lambdaAwsmPkgs;
});
});
@ -99,19 +100,16 @@ CMD.prototype._promptStage = Promise.method(function() {
var _this = this;
// If stage exists, skip
if (_this._stage) return;
if (_this._stage) {
return Promise.resolve();
}
var stages = Object.keys(_this._JAWS._meta.projectJson.stages);
// Check if project has stages
if (!stages.length) {
throw new JawsError('This project has no stages');
}
// If project only has 1 stage, skip prompt
if (stages.length === 1) {
_this._stage = stages[0];
return;
return Promise.resolve();
}
// Create Choices
@ -189,7 +187,7 @@ function Deployer(JAWS, lambdaPaths, stage, region, noExeCf) {
/**
* Deploy lambdas
*
* @returns {Promise} list of full lambda awsm.json paths that were deployed
* @returns {Promise} map of lambdaAwsmPaths to {Code:{},lambdaName:""}
*/
Deployer.prototype.deploy = Promise.method(function() {
@ -198,7 +196,7 @@ Deployer.prototype.deploy = Promise.method(function() {
awsmLambdas = {};
return Promise.try(function() {
})
})
.bind(_this)
.then(function() {
return _this._lambdaAwsmPaths;
@ -218,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: {
@ -248,9 +246,9 @@ Deployer.prototype.deploy = Promise.method(function() {
var lambdaRoleArn = utils.getProjRegionConfigForStage(_this._JAWS._meta.projectJson, _this._stage, _this._region);
if (existingStack) {
return AWSUtils.cfUpdateLambdasStack(_this._stage, _this._region);
return AWSUtils.cfUpdateLambdasStack(_this._JAWS,_this._stage, _this._region);
} else {
return AWSUtils.cfCreateLambdasStack(_this._stage, _this._region);
return AWSUtils.cfCreateLambdasStack(_this._JAWS,_this._stage, _this._region);
}
}
})
@ -280,8 +278,8 @@ Deployer.prototype._generateLambdaCf = function(taggedLambdaPkgs) {
existingStack = true;
return AWSUtils.cfGetLambdasStackTemplate(
_this.JAWS._meta.profile, _this._region, _this._stage, _this._JAWS._meta.projectJson.name
)
_this.JAWS._meta.profile, _this._region, _this._stage, _this._JAWS._meta.projectJson.name
)
.error(function(e) {
if (e && e.code !== 'ResourceNotFoundException') {
console.error(

View File

@ -98,7 +98,7 @@ CMD.prototype._createSkeleton = Promise.method(function() {
var actionPath = path.join(
_this._JAWS._meta.projectRootPath,
'back',
'lambdas',
'aws_modules',
_this._action.resource,
_this._action.action);
@ -124,7 +124,7 @@ CMD.prototype._createSkeleton = Promise.method(function() {
// Edit jaws.json
actionJson.lambda.cloudFormation.Runtime = 'nodejs';
actionJson.lambda.cloudFormation.Handler = path.join(
'lambdas',
'aws_modules',
_this._action.resource,
_this._action.action,
'index.handler');

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)
@ -325,11 +325,11 @@ CMD.prototype._createProjectDirectory = Promise.method(function() {
// 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')),
@ -389,12 +389,13 @@ CMD.prototype._createCfStack = Promise.method(function() {
// Create CF stack
return AWSUtils.cfCreateResourcesStack(
_this._profile,
_this._region,
_this._projectRootPath,
_this._name,
_this._stage,
_this._notificationEmail)
_this._profile,
_this._region,
_this._projectRootPath,
_this._name,
_this._stage,
_this._s3Bucket,
_this._notificationEmail)
.then(function(cfData) {
return AWSUtils.monitorCfCreate(cfData, _this._profile, _this._region);
});

View File

@ -185,13 +185,14 @@ CMD.prototype._createCfStack = Promise.method(function() {
spinner.start();
return AWSUtils.cfCreateResourcesStack(
_this._JAWS._meta.profile,
_this._region,
_this._JAWS._meta.projectRootPath,
_this._JAWS._meta.projectJson.name,
_this._stage,
'' // TODO: read email out of existing jaws-cf.json?
)
_this._JAWS._meta.profile,
_this._region,
_this._JAWS._meta.projectRootPath,
_this._JAWS._meta.projectJson.name,
_this._stage,
_this._JAWS._meta.projectJson.jawsBuckets[_this._region],
'' // TODO: read email out of existing jaws-cf.json?
)
.then(function(cfData) {
return AWSUtils.monitorCfCreate(cfData, _this._JAWS._meta.profile, _this._region)
.then(function(cfData) {

View File

@ -173,13 +173,107 @@ 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;
});
};
exports.putCfFile = function(awsProfile, projRootPath, awsRegion, bucketName, projName, projStage, type) {
if (['lambdas', 'resources'].indexOf(type) == -1) {
Promise.reject(new JawsError('Type ' + type + ' invalid. Must be lambdas or resources', JawsError.errorCodes.UNKNOWN));
}
var d = new Date(),
cfPath = path.join(projRootPath, 'cloudformation', projStage, awsRegion, type + '-cf.json'),
key = ['JAWS', projName, projStage, 'cloudformation/' + type].join('/') + '@' + d.getTime() + '.json',
params = {
Bucket: bucketName,
Key: key,
ACL: 'private',
ContentType: 'application/json',
Body: fs.readfileSync(cfPath),
};
return this.putS3Object(awsProfile, awsRegion, params)
.then(function() {
return key;
})
};
exports.cfCreateLambdasStack = function(JAWS, stage, region, lambdaRoleArn) {
var _this = this,
profile = JAWS._meta._profile,
projRootPath = JAWS._meta.projectRootPath,
bucketName = JAWS._meta.projectJson.jawsBuckets[region],
projName = JAWS._meta.projectJson.name;
_this.configAWS(profile, region);
var CF = Promise.promisifyAll(new AWS.CloudFormation({
apiVersion: '2010-05-15',
})),
stackName = _this.cfGetLambdasStackName(stage, projName);
var params = {
StackName: stackName,
Capabilities: [],
OnFailure: 'ROLLBACK',
Parameters: [{
ParameterKey: 'aaLambdaRoleArn',
ParameterValue: lambdaRoleArn,
UsePreviousValue: false,
},],
Tags: [{
Key: 'STAGE',
Value: stage,
},],
};
return _this.putCfFile(awsProfile, projRootPath, region, bucketName, projName, stage, 'lambdas')
.then(function(s3CfKey) {
params.TemplateURL = s3CfKey;
return CF.createStackAsync(params);
});
};
exports.cfUpdateLambdasStack = function(JAWS, stage, region) {
var _this = this,
profile = JAWS._meta._profile,
projRootPath = JAWS._meta.projectRootPath,
bucketName = JAWS._meta.projectJson.jawsBuckets[region],
projName = JAWS._meta.projectJson.name;
_this.configAWS(profile, region);
var CF = Promise.promisifyAll(new AWS.CloudFormation({
apiVersion: '2010-05-15',
})),
stackName = _this.cfGetLambdasStackName(stage, projName);
var params = {
StackName: stackName,
Capabilities: [],
OnFailure: 'ROLLBACK',
Parameters: [{
ParameterKey: 'aaLambdaRoleArn',
ParameterValue: lambdaRoleArn,
UsePreviousValue: false,
},],
Tags: [{
Key: 'STAGE',
Value: stage,
},],
};
return _this.putCfFile(awsProfile, projRootPath, region, bucketName, projName, stage, 'lambdas')
.then(function(s3CfKey) {
params.TemplateURL = s3CfKey;
return CF.createStackAsync(params);
});
};
/**
* CloudFormation: Create Stack
*
@ -192,69 +286,58 @@ exports.cfGetLambdasStackTemplate = function(awsProfile, awsRegion, stage, projN
* @returns {Promise}
*/
exports.cfCreateResourcesStack = function(awsProfile, awsRegion, projRootPath, projName, projStage, projNotificationEmail) {
exports.cfCreateResourcesStack = function(awsProfile, awsRegion, projRootPath, projName, projStage, bucketName, projNotificationEmail) {
var _this = this;
return new Promise(function(resolve, reject) {
_this.configAWS(awsProfile, awsRegion);
// Config AWS
_this.configAWS(awsProfile, awsRegion);
var CF = Promise.promisifyAll(new AWS.CloudFormation({
apiVersion: '2010-05-15',
})),
stackName = _this.cfGetResourcesStackName(projStage, projName);
// Instantiate
var CF = new AWS.CloudFormation({
apiVersion: '2010-05-15',
});
var params = {
StackName: stackName,
Capabilities: [
'CAPABILITY_IAM',
],
OnFailure: 'ROLLBACK',
Parameters: [{
ParameterKey: 'aaProjectName',
ParameterValue: projName,
UsePreviousValue: false,
}, {
ParameterKey: 'aaStage',
ParameterValue: projStage,
UsePreviousValue: false,
}, {
ParameterKey: 'aaDataModelPrefix',
ParameterValue: projStage,
UsePreviousValue: false,
}, {
ParameterKey: 'aaHostedZoneName',
ParameterValue: 'mydomain.com', //TODO: should we prompt for this?
UsePreviousValue: false,
}, {
ParameterKey: 'aaNotficationEmail',
ParameterValue: projNotificationEmail,
UsePreviousValue: false,
}, {
ParameterKey: 'aaDefaultDynamoRWThroughput',
ParameterValue: '1',
UsePreviousValue: false,
},],
Tags: [{
Key: 'STAGE',
Value: projStage,
},],
};
var params = {
StackName: _this.cfGetResourcesStackName(projStage, projName),
Capabilities: [
'CAPABILITY_IAM',
],
OnFailure: 'ROLLBACK',
Parameters: [{
ParameterKey: 'aaProjectName',
ParameterValue: projName,
UsePreviousValue: false,
}, {
ParameterKey: 'aaStage',
ParameterValue: projStage,
UsePreviousValue: false,
}, {
ParameterKey: 'aaDataModelPrefix',
ParameterValue: projStage,
UsePreviousValue: false,
}, {
ParameterKey: 'aaHostedZoneName',
ParameterValue: 'mydomain.com', //TODO: should we prompt for this?
UsePreviousValue: false,
}, {
ParameterKey: 'aaNotficationEmail',
ParameterValue: projNotificationEmail,
UsePreviousValue: false,
}, {
ParameterKey: 'aaDefaultDynamoRWThroughput',
ParameterValue: '1',
UsePreviousValue: false,
},],
Tags: [{
Key: 'STAGE',
Value: projStage,
},],
// Gotta be careful, TemplateBody has a limit of 51,200 bytes. If we hit limit use TemplateURL
TemplateBody: JSON.stringify(require(path.join(projRootPath, 'jaws-cf.json'))),
};
CF.createStack(params, function(error, data) {
if (error) {
console.error(error);
return reject(new JawsError(error.message, JawsError.errorCodes.UNKNOWN));
} else {
return resolve(data);
}
});
});
return _this.putCfFile(awsProfile, projRootPath, awsRegion, bucketName, projName, projStage, 'resources')
.then(function(s3CfKey) {
params.TemplateURL = s3CfKey;
return CF.createStackAsync(params);
});
};
/**
@ -262,7 +345,7 @@ exports.cfCreateResourcesStack = function(awsProfile, awsRegion, projRootPath, p
* @param cfData
* @param awsProfile
* @param region
* @returns {bluebird|exports|module.exports}
* @returns {Promise}
*/
exports.monitorCfCreate = function(cfData, awsProfile, region) {

View File

@ -207,7 +207,7 @@ module.exports.writeFile = function(filePath, contents) {
*/
module.exports.generateLambdaName = function(lambdaAwsmJson) {
var handlerName = lambdaAwsmJson.cloudFormation.Handler.replace('lambdas', ''),
var handlerName = lambdaAwsmJson.cloudFormation.Handler.replace('aws_modules', ''),
resourceAction = handlerName.substr(0, handlerName.lastIndexOf('/'));
return 'l' + resourceAction.replace(/\/([a-z])/g, function(g) {

View File

@ -31,9 +31,9 @@ describe('Test deploy endpoint command', function() {
JAWS = new Jaws();
// Get Lambda Paths
lambdaPaths.lambda1 = path.join(projPath, 'back', 'lambdas', 'sessions', 'show', 'jaws.json');
lambdaPaths.lambda2 = path.join(projPath, 'back', 'lambdas', 'sessions', 'create', 'jaws.json');
lambdaPaths.lambda3 = path.join(projPath, 'back', 'lambdas', 'users', 'create', 'jaws.json');
lambdaPaths.lambda1 = path.join(projPath, 'back', 'aws_modules', 'sessions', 'show', 'jaws.json');
lambdaPaths.lambda2 = path.join(projPath, 'back', 'aws_modules', 'sessions', 'create', 'jaws.json');
lambdaPaths.lambda3 = path.join(projPath, 'back', 'aws_modules', 'users', 'create', 'jaws.json');
}).then(done);
});

View File

@ -24,7 +24,7 @@ describe('Test "env" 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();
});

View File

@ -25,7 +25,7 @@ describe('Test "install" 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();
});

View File

@ -32,9 +32,9 @@ describe('Test "tag" command', function() {
JAWS = new Jaws();
// Get Lambda Paths
modulePaths.lambda1 = path.join(projPath, 'back', 'lambdas', 'sessions', 'show', 'awsm.json');
modulePaths.lambda2 = path.join(projPath, 'back', 'lambdas', 'sessions', 'create', 'awsm.json');
modulePaths.lambda3 = path.join(projPath, 'back', 'lambdas', 'users', 'create', 'awsm.json');
modulePaths.lambda1 = path.join(projPath, 'back', 'aws_modules', 'sessions', 'show', 'awsm.json');
modulePaths.lambda2 = path.join(projPath, 'back', 'aws_modules', 'sessions', 'create', 'awsm.json');
modulePaths.lambda3 = path.join(projPath, 'back', 'aws_modules', 'users', 'create', 'awsm.json');
done();
});