diff --git a/lib/defaults/actions/EnvList.js b/lib/defaults/actions/EnvList.js index 2265e33a2..e65784932 100644 --- a/lib/defaults/actions/EnvList.js +++ b/lib/defaults/actions/EnvList.js @@ -26,6 +26,7 @@ class EnvList extends JawsPlugin { constructor(Jaws, config) { super(Jaws, config); + this.evt = {}; } /** @@ -45,10 +46,26 @@ class EnvList extends JawsPlugin { this.Jaws.addAction(this.envList.bind(this), { handler: 'envList', description: `List env vars for stage and region. Region can be 'all' -usage: jaws env list `, +usage: jaws env list`, context: 'env', contextAction: 'list', - options: [], + options: [ + { + option: 'region', + shortcut: 'r', + description: 'region you want to list env vars for' + }, + { + option: 'stage', + shortcut: 's', + description: 'stage you want to list env vars for' + }, + { + option: 'nonInteractive', + shortcut: 'i', + description: 'Optional - Turn off CLI interactivity if true. Default: false' + }, + ], }); return BbPromise.resolve(); } @@ -60,75 +77,186 @@ usage: jaws env list `, * @returns {Promise} */ envList(evt) { - if (this.Jaws.cli) { - - // Add options to evt - this.evt = this.Jaws.cli.options; - - // Add region & stage from params. - this.evt.stage = this.Jaws.cli.params[0]; - this.evt.region = this.Jaws.cli.params[1]; - - } - - if (!this.evt.stage || !this.evt.region) { - return BbPromise.reject(new JawsError('Must specify a stage and region'), JawsError.errorCodes.UNKNOWN); - } - - let _this = this; - let awsModsDir = path.join(this.Jaws._projectRootPath, 'back', 'slss_modules'); + if(evt) { + _this.evt = evt; + _this.Jaws._interactive = false; + } - return JawsUtils.findAllAwsmJsons(awsModsDir) - .then(awsmJsonPaths => { - return [awsmJsonPaths, awsMisc.getEnvFiles(_this.Jaws, _this.evt.region, _this.evt.stage)]; - }) - .spread((awsmJsonPaths, envMapsByRegion) => { - let envInBackMap = {}; - JawsCLI.log(`ENV vars for stage ${_this.evt.stage}:`); - envMapsByRegion.forEach(mapForRegion => { - JawsCLI.log('------------------------------'); - JawsCLI.log(mapForRegion.regionName); - JawsCLI.log('------------------------------'); - console.log(chalk.bold(mapForRegion.raw + '') + '\n'); + // If CLI, parse arguments + if (_this.Jaws.cli) { + _this.evt = _this.Jaws.cli.options; + + if (_this.Jaws.cli.options.nonInteractive) { + _this.Jaws._interactive = false; + } + } + + return _this.Jaws.validateProject() + .bind(_this) + .then(_this._promptStage) + .then(_this._promptRegion) + .then(_this._validateAndPrepare) + .then(_this._listEnvVars); + } + + + _promptStage() { + let _this = this; + let stages = Object.keys(_this.Jaws._projectJson.stages); + + + // Skip if non-interactive + if (!_this.Jaws._interactive || _this.evt.stage) return BbPromise.resolve(); + + // if project has 1 stage, skip prompt + if (stages.length === 1) { + _this.evt.stage = stages[0]; + return BbPromise.resolve(); + } + // add local stage + stages.push('local'); + + // Create Choices + let choices = []; + for (let i = 0; i < stages.length; i++) { + choices.push({ + key: (i + 1) + ') ', + value: stages[i], + label: stages[i], }); + } - //first build up a list of all env vars awsm modules say they need - awsmJsonPaths.forEach(ajp => { - let awsmJson = require(ajp); - if (awsmJson.envVars) { - awsmJson.envVars.forEach(function(key) { - let rel = path.relative(awsModsDir, ajp); - if (envInBackMap[key]) { - envInBackMap[key].push(rel); - } else { - envInBackMap[key] = [rel]; - } + return JawsCLI.select('Which stage are you listing env vars for: ', choices, false) + .then(function(results) { + _this.evt.stage = results[0].value; + }); + } + + _promptRegion() { + let _this = this; + + // skip region prompt if selected stage is 'local' + if (_this.evt.stage === 'local') { + _this.evt.region = 'local'; + return BbPromise.resolve(); + } + + if (!_this.Jaws._interactive || _this.evt.region) return BbPromise.resolve(); + + // TODO: list only regions defined in the provided Stage + // this assumres that the provided stage is valid, we'll have to validate before getting here + let choices = awsMisc.validLambdaRegions.map(r => { + return { + key: '', + value: r, + label: r, + }; + }); + + // adding local & all regions + choices.push( + { + key: '', + value: 'all', + label: 'all', + } + ); + + return _this.selectInput('Select a region for your stage: ', choices, false) + .then(results => { + _this.evt.region = results[0].value; + }); + } + + _validateAndPrepare() { + let _this = this; + + // non interactive validation + if (!this.Jaws._interactive) { + + // Check API Keys + if (!this.Jaws._awsProfile) { + if (!this.Jaws._awsAdminKeyId || !this.Jaws._awsAdminSecretKey) { + return BbPromise.reject(new JawsError('Missing AWS Profile and/or API Key and/or AWS Secret Key')); + } + } + // Check Params + if (!this.evt.stage || !this.evt.region) { + return BbPromise.reject(new JawsError('Missing stage or region')); + } + } + + // validate stage: make sure stage exists + if (!_this.Jaws._projectJson.stages[_this.evt.stage] && _this.evt.stage != 'local') { + return BbPromise.reject(new JawsError('Stage ' + _this.evt.stage + ' does not exist in your project', JawsError.errorCodes.UNKNOWN)); + } + + if (_this.evt.stage != 'local' && _this.evt.region != 'all') { + // validate region: make sure region exists in stage + if (!_this.Jaws._projectJson.stages[_this.evt.stage].some(function(r) { + return r.region == _this.evt.region; + })) { + return BbPromise.reject(new JawsError('Region "' + _this.evt.region + '" does not exist in stage "' + _this.evt.stage + '"')); + } + } + + } + + _listEnvVars() { + let _this = this; + let awsModsDir = path.join(_this.Jaws._projectRootPath, 'back', 'slss_modules'); + + return JawsUtils.findAllAwsmJsons(awsModsDir) + .then(awsmJsonPaths => { + return [awsmJsonPaths, awsMisc.getEnvFiles(_this.Jaws, _this.evt.region, _this.evt.stage)]; + }) + .spread((awsmJsonPaths, envMapsByRegion) => { + let envInBackMap = {}; + JawsCLI.log(`ENV vars for stage ${_this.evt.stage}:`); + envMapsByRegion.forEach(mapForRegion => { + JawsCLI.log('------------------------------'); + JawsCLI.log(mapForRegion.regionName); + JawsCLI.log('------------------------------'); + console.log(chalk.bold(mapForRegion.raw + '') + '\n'); + }); + + //first build up a list of all env vars awsm modules say they need + awsmJsonPaths.forEach(ajp => { + let awsmJson = require(ajp); + if (awsmJson.envVars) { + awsmJson.envVars.forEach(function(key) { + let rel = path.relative(awsModsDir, ajp); + if (envInBackMap[key]) { + envInBackMap[key].push(rel); + } else { + envInBackMap[key] = [rel]; + } + }); + } + }); + + let awsmKeys = Object.keys(envInBackMap); + if (awsmKeys.length) { + JawsCLI.log('awsm.json:lambda.envVars and regions where they are used (red means NOT defined in region):'); + awsmKeys.forEach(key => { + let regionNamesColored = envMapsByRegion.map(rMap => { + return (!rMap.vars[key]) ? chalk.white.bgRed(rMap.regionName) : rMap.regionName; + }); + + JawsCLI.log('------------------------------'); + JawsCLI.log(key); + JawsCLI.log('------------------------------'); + + JawsCLI.log(chalk.bold('aws mods using') + ': ' + envInBackMap[key].join(',')); + JawsCLI.log(chalk.bold('regions') + ': ' + regionNamesColored.join(',') + '\n'); }); } + + return envMapsByRegion; }); - - let awsmKeys = Object.keys(envInBackMap); - if (awsmKeys.length) { - JawsCLI.log('awsm.json:lambda.envVars and regions where they are used (red means NOT defined in region):'); - awsmKeys.forEach(key => { - let regionNamesColored = envMapsByRegion.map(rMap => { - return (!rMap.vars[key]) ? chalk.white.bgRed(rMap.regionName) : rMap.regionName; - }); - - JawsCLI.log('------------------------------'); - JawsCLI.log(key); - JawsCLI.log('------------------------------'); - - JawsCLI.log(chalk.bold('aws mods using') + ': ' + envInBackMap[key].join(',')); - JawsCLI.log(chalk.bold('regions') + ': ' + regionNamesColored.join(',') + '\n'); - }); - } - - return envMapsByRegion; - }); - } + } } module.exports = EnvList; diff --git a/lib/defaults/actions/ProjectCreate.js b/lib/defaults/actions/ProjectCreate.js index e6f4a3756..14f778ff7 100644 --- a/lib/defaults/actions/ProjectCreate.js +++ b/lib/defaults/actions/ProjectCreate.js @@ -86,7 +86,7 @@ class ProjectCreate extends JawsPlugin { */ createProject(evt) { - let _this = this; + let _this = this; if(evt) { _this.evt = evt; @@ -94,18 +94,18 @@ class ProjectCreate extends JawsPlugin { } // If CLI, parse arguments - if (this.Jaws.cli) { - this.evt = this.Jaws.cli.options; - this.Jaws._awsProfile = this.evt.profile + if (_this.Jaws.cli) { + _this.evt = this.Jaws.cli.options; + _this.Jaws._awsProfile = this.evt.profile - if (this.Jaws.cli.options.nonInteractive) { - this.Jaws._interactive = false; + if (_this.Jaws.cli.options.nonInteractive) { + _this.Jaws._interactive = false; } } // Add default runtime - if (!this.evt.runtime) { - this.evt.runtime = 'nodejs'; + if (!_this.evt.runtime) { + _this.evt.runtime = 'nodejs'; } diff --git a/lib/defaults/actions/RegionCreate.js b/lib/defaults/actions/RegionCreate.js index 8e533e501..d2fa3fe2c 100644 --- a/lib/defaults/actions/RegionCreate.js +++ b/lib/defaults/actions/RegionCreate.js @@ -79,15 +79,15 @@ usage: jaws region create`, } // If CLI, parse arguments - if (this.Jaws.cli) { - this.evt = this.Jaws.cli.options; + if (_this.Jaws.cli) { + _this.evt = _this.Jaws.cli.options; - if (this.Jaws.cli.options.nonInteractive) { - this.Jaws._interactive = false; + if (_this.Jaws.cli.options.nonInteractive) { + _this.Jaws._interactive = false; } } - return this.Jaws.validateProject() + return _this.Jaws.validateProject() .bind(_this) .then(_this._promptStage) .then(_this._promptRegion) @@ -309,7 +309,7 @@ JAWS_DATA_MODEL_STAGE=${stage}`; let regionObj = { region: _this.evt.region, iamRoleArnLambda: '', - jawsBucket: _this.evt.projectBucket, + projectBucket: _this.evt.projectBucket, apiFunctionAlias: 'LATEST', }; diff --git a/lib/defaults/actions/ResourcesDeploy.js b/lib/defaults/actions/ResourcesDeploy.js index 3f268a892..1c0769cc8 100644 --- a/lib/defaults/actions/ResourcesDeploy.js +++ b/lib/defaults/actions/ResourcesDeploy.js @@ -115,7 +115,7 @@ ex: // If stage exists, skip if (!this.evt.stage) { - stages = Object.keys(_this.Jaws._projectJson.stage); + stages = Object.keys(_this.Jaws._projectJson.stages); // If project only has 1 stage, skip prompt if (stages.length === 1) { @@ -144,7 +144,7 @@ ex: // If region exists, skip if (!_this.evt.region) { - regions = this.Jaws._projectJson.stage[_this.evt.stage]; + regions = this.Jaws._projectJson.stages[_this.evt.stage]; // If project only has 1 region, skip prompt if (regions.length === 1) { diff --git a/lib/defaults/actions/StageCreate.js b/lib/defaults/actions/StageCreate.js index 4fc82fd14..d577cb3fc 100644 --- a/lib/defaults/actions/StageCreate.js +++ b/lib/defaults/actions/StageCreate.js @@ -79,15 +79,15 @@ usage: jaws stage create`, } // If CLI, parse arguments - if (this.Jaws.cli) { - this.evt = this.Jaws.cli.options; + if (_this.Jaws.cli) { + _this.evt = _this.Jaws.cli.options; - if (this.Jaws.cli.options.nonInteractive) { - this.Jaws._interactive = false; + if (_this.Jaws.cli.options.nonInteractive) { + _this.Jaws._interactive = false; } } - return this.Jaws.validateProject() + return _this.Jaws.validateProject() .bind(_this) .then(_this._promptStage) .then(_this._promptRegion) @@ -343,7 +343,7 @@ JAWS_DATA_MODEL_STAGE=${stage}`; regionObj = { region: _this.evt.region, iamRoleArnLambda: '', - jawsBucket: _this._projectBucket, + projectBucket: _this._projectBucket, apiFunctionAlias: 'LATEST', }; diff --git a/lib/utils/aws/Misc.js b/lib/utils/aws/Misc.js index 56fc19f25..df9633a85 100644 --- a/lib/utils/aws/Misc.js +++ b/lib/utils/aws/Misc.js @@ -116,11 +116,11 @@ module.exports.getEnvFiles = function(Jaws, region, stage) { })); } else { //All regions - if (!Jaws._projectJson.stage[stage]) { + if (!Jaws._projectJson.stages[stage]) { return Promise.reject(new JawsError(`Invalid stage ${stage}`, JawsError.errorCodes.UNKNOWN)); } - Jaws._projectJson.stage[stage].forEach(regionCfg => { + Jaws._projectJson.stages[stage].forEach(regionCfg => { regionGets.push( _this.getEnvFileAsMap(Jaws, regionCfg.region, stage) .then(envVars => { @@ -138,7 +138,7 @@ module.exports.getEnvFileAsMap = function(Jaws, region, stage) { if (stage == 'local') { deferred = Promise.resolve(fs.readFileSync(path.join(Jaws._projectRootPath, '.env'))); } else { - let bucket = JawsUtils.getProjRegionConfigForStage(Jaws._projectJson, stage, region).regionBucket; + let bucket = JawsUtils.getProjRegionConfigForStage(Jaws._projectJson, stage, region).projectBucket; let config = { profile: Jaws._awsProfile, region: region