From 4ff2af67ae3eab90e16dc97b96c667a1f8f8a872 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Mon, 8 Feb 2016 16:40:18 +0100 Subject: [PATCH 01/17] Component search path made more flexible and portable --- lib/ServerlessPlugin.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/ServerlessPlugin.js b/lib/ServerlessPlugin.js index 689145340..149a31a5c 100644 --- a/lib/ServerlessPlugin.js +++ b/lib/ServerlessPlugin.js @@ -61,14 +61,11 @@ class ServerlessPlugin { // Strip project path from cwd cwd = cwd.replace(projectPath, '').split(path.sep); - // In component - if (cwd.length === 2) return cwd[1]; - // In component subfolder 1 - if (cwd.length === 3) return cwd[1] + '/' + cwd[2]; - // In component subfolder 2 - if (cwd.length === 4) return cwd[1] + '/' + cwd[2] + '/' + cwd[3]; - // In component subfolder 3 - if (cwd.length === 5) return cwd[1] + '/' + cwd[2] + '/' + cwd[3] + '/' + cwd[4]; + cwd.shift(); + + if( cwd.length > 0 ) { + return path.join.apply( path, cwd ) + } return false; } From e0e027dcd3e37ace99cfb15594ec0da06dfc9fc7 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Tue, 9 Feb 2016 15:14:17 +0100 Subject: [PATCH 02/17] Refactoring: removed S.config.projectPath, Project instance is created at correct moments, common project helpers moved to Project --- bin/serverless | 7 +-- lib/Serverless.js | 42 +++++++++---- lib/ServerlessComponent.js | 12 ++-- lib/ServerlessEndpoint.js | 15 ++--- lib/ServerlessFunction.js | 15 +++-- lib/ServerlessMeta.js | 35 ++++++----- lib/ServerlessProject.js | 85 +++++++++++++++++++------- lib/ServerlessState.js | 40 ++++++------ lib/actions/CodePackageLambda.js | 2 +- lib/actions/ComponentCreate.js | 8 +-- lib/actions/DashDeploy.js | 2 +- lib/actions/EndpointDeploy.js | 2 +- lib/actions/EnvSet.js | 2 +- lib/actions/EnvUnset.js | 2 +- lib/actions/FunctionCreate.js | 12 ++-- lib/actions/FunctionDeploy.js | 6 +- lib/actions/FunctionLogs.js | 2 +- lib/actions/FunctionRun.js | 4 +- lib/actions/ModuleInstall.js | 4 +- lib/actions/ProjectInit.js | 61 ++++++++---------- lib/actions/ProjectInstall.js | 9 ++- lib/actions/RegionRemove.js | 2 +- lib/actions/ResourcesDeploy.js | 3 +- lib/actions/ResourcesRemove.js | 3 +- lib/actions/StageRemove.js | 2 +- lib/utils/aws/Misc.js | 2 +- lib/utils/aws/S3.js | 3 +- lib/utils/index.js | 36 ----------- tests/tests/actions/ResourcesDeploy.js | 2 +- 29 files changed, 211 insertions(+), 209 deletions(-) diff --git a/bin/serverless b/bin/serverless index 79436123e..738f5e13f 100755 --- a/bin/serverless +++ b/bin/serverless @@ -7,10 +7,9 @@ let argv = require('minimist')(process.argv.slice(2)); if (argv.debug) process.env.DEBUG = '*'; let S = require('../lib/Serverless'), - SUtils = require('../lib/utils/index'), - serverless = new S({ - interactive: typeof process.env.CI !== 'undefined' ? false : true, - projectPath: SUtils.getProjectPath(process.cwd()) + Project = require('../lib/ServerlessProject'), + serverless = new S( Project.findProject(process.cwd()), { + interactive: typeof process.env.CI !== 'undefined' ? false : true }); serverless.command(argv); \ No newline at end of file diff --git a/lib/Serverless.js b/lib/Serverless.js index c4dd2d00c..d5308cbe6 100644 --- a/lib/Serverless.js +++ b/lib/Serverless.js @@ -25,7 +25,7 @@ BbPromise.longStackTraces(); class Serverless { - constructor(config) { + constructor(project, config) { // Add version this._version = require('./../package.json').version; @@ -36,10 +36,11 @@ class Serverless { interactive: false, awsAdminKeyId: null, awsAdminSecretKey: null, - projectPath: null, serverlessPath: __dirname }; + this.setProject( project ); + // Add Config Settings this.updateConfig(config); @@ -48,6 +49,7 @@ class Serverless { this.hooks = {}; this.commands = {}; this.classes = { + // TODO: add Runtime, Stage, Region State: require('./ServerlessState'), Meta: require('./ServerlessMeta'), Project: require('./ServerlessProject'), @@ -58,13 +60,13 @@ class Serverless { this.cli = null; this.state = new this.classes.State(this); - // If project - if (this.config.projectPath) { + if (this.hasProject()) { + // TODO: move this to Project class, along with credentials // Load Admin ENV information require('dotenv').config({ silent: true, // Don't display dotenv load failures for admin.env if we already have the required environment variables - path: path.join(this.config.projectPath, 'admin.env') + path: path.join(this.getProject().getRootPath(), 'admin.env') }); this._setCredentials(); @@ -73,12 +75,22 @@ class Serverless { // Load Plugins: Framework Defaults let defaults = require('./Actions.json'); this._loadPlugins(__dirname, defaults.plugins); + this.loadProjectPlugins(); + } - // Load Plugins: Project - if (this.config.projectPath && SUtils.fileExistsSync(path.join(this.config.projectPath, 's-project.json'))) { - let projectJson = require(path.join(this.config.projectPath, 's-project.json')); - if (projectJson.plugins) this._loadPlugins(this.config.projectPath, projectJson.plugins); - } + getProject() { + return this.project; + } + + hasProject() { + return this.project != undefined; + } + + setProject( project ) { + this.project = project; + + // TODO: get rid of this? Seems like responsibility of Serverless and Project classes is too tangled together + project.setServerless( this ); } /** @@ -138,7 +150,7 @@ class Serverless { options: extend(_this.cli.options, _this.cli.params) }; - if (_this.config.projectPath) return _this.init(); + if (_this.hasProject()) return _this.init(); } else { @@ -219,6 +231,12 @@ class Serverless { this.config = extend(this.config, config); } + loadProjectPlugins() { + if( this.hasProject() ) { + this._loadPlugins( this.getProject().getRootPath(), this.getProject().getPlugins() ); + } + } + /** * Load Plugins * - @param relDir string path to start from when rel paths are specified @@ -315,7 +333,7 @@ class Serverless { } // if not in project root and not creating project, throw error - if (!this.config.projectPath && _this.cli.context != 'project') { + if (!this.hasProject() && _this.cli.context != 'project') { return BbPromise.reject(new SError('This command can only be run inside a Serverless project.')); } diff --git a/lib/ServerlessComponent.js b/lib/ServerlessComponent.js index c21f0e28c..a4d71fbfe 100644 --- a/lib/ServerlessComponent.js +++ b/lib/ServerlessComponent.js @@ -54,8 +54,8 @@ class ServerlessComponent { } // Make full path - if (this._S.config.projectPath && this._config.sPath) { - this._config.fullPath = path.join(this._S.config.projectPath, this._config.sPath); + if (this._S.hasProject() && this._config.sPath) { + this._config.fullPath = this._S.getProject().getFilePath(this._config.sPath); } } @@ -87,7 +87,7 @@ class ServerlessComponent { return BbPromise.try(function() { // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Component could not be loaded because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Component could not be loaded because no project path has been set on Serverless instance'); // Validate: Check component exists if (!SUtils.fileExistsSync(path.join(_this._config.fullPath, 's-component.json'))) { @@ -214,7 +214,7 @@ class ServerlessComponent { if (!options.stage || !options.region) throw new SError('Both "stage" and "region" params are required'); // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Component could not be populated because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Component could not be populated because no project path has been set on Serverless instance'); // Populate let clone = _this.get(); @@ -253,7 +253,7 @@ class ServerlessComponent { return new BbPromise.try(function() { // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Component could not be saved because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Component could not be saved because no project path has been set on Serverless instance'); // Create if does not exist if (!SUtils.fileExistsSync(path.join(_this._config.fullPath, 's-component.json'))) { @@ -344,7 +344,7 @@ class ServerlessComponent { */ getProject() { - return this._S.state.project; + return this._S.getProject(); } } diff --git a/lib/ServerlessEndpoint.js b/lib/ServerlessEndpoint.js index 1efea82d8..a3b2a33dd 100644 --- a/lib/ServerlessEndpoint.js +++ b/lib/ServerlessEndpoint.js @@ -69,11 +69,8 @@ class ServerlessEndpoint { } // Make full path - if (this._S.config.projectPath && this._config.sPath) { - this._config.fullPath = path.join( - this._S.config.projectPath, - this._config.sPath.split('@')[0].split('/').join(path.sep) - ); + if (this._S.hasProject() && this._config.sPath) { + this._config.fullPath = this._S.getProject().getFilePath( this._config.sPath.split('@')[0].split('/') ); } } @@ -90,7 +87,7 @@ class ServerlessEndpoint { return new BbPromise(function(resolve) { // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Endpoint could not be loaded because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Endpoint could not be loaded because no project path has been set on Serverless instance'); // Validate: Check function exists if (!SUtils.fileExistsSync(path.join(_this._config.fullPath, 's-function.json'))) { @@ -152,7 +149,7 @@ class ServerlessEndpoint { if (!options.stage || !options.region) throw new SError('Both "stage" and "region" params are required'); // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Endpoint could not be populated because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Endpoint could not be populated because no project path has been set on Serverless instance'); // Populate let clone = _this.get(); @@ -187,7 +184,7 @@ class ServerlessEndpoint { return new BbPromise(function(resolve) { // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Endpoint could not be saved because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Endpoint could not be saved because no project path has been set on Serverless instance'); // Validate: Check function exists if (!SUtils.fileExistsSync(path.join(_this._config.fullPath, 's-function.json'))) { @@ -219,7 +216,7 @@ class ServerlessEndpoint { */ getProject() { - return this._S.state.project; + return this._S.getProject(); } /** diff --git a/lib/ServerlessFunction.js b/lib/ServerlessFunction.js index 8146de9ae..64724b3df 100644 --- a/lib/ServerlessFunction.js +++ b/lib/ServerlessFunction.js @@ -97,8 +97,8 @@ class ServerlessFunction { } // Make full path - if (this._S.config.projectPath && this._config.sPath) { - this._config.fullPath = path.join(this._S.config.projectPath, this._config.sPath.split('/').join(path.sep)); + if (this._S.hasProject() && this._config.sPath) { + this._config.fullPath = this._S.getProject().getFilePath( this._config.sPath.split('/') ); } } @@ -116,7 +116,7 @@ class ServerlessFunction { return BbPromise.try(function() { // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Function could not be loaded because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Function could not be loaded because no project path has been set on Serverless instance'); // Validate: Check function exists if (!SUtils.fileExistsSync(path.join(_this._config.fullPath, 's-function.json'))) { @@ -215,8 +215,7 @@ class ServerlessFunction { if (this._config.sPath.split('/').length == 3) { // Check if s-module.json exists in subfolder - if (SUtils.fileExistsSync(path.join( - this._S.config.projectPath, + if (SUtils.fileExistsSync(this._S.getProject().getFilePath( this._config.sPath.split('/').splice(0, 2).join(path.sep), 's-module.json'))) { name = name + '-' + this._config.sPath.split('/')[1]; @@ -252,7 +251,7 @@ class ServerlessFunction { if (!options.stage || !options.region) throw new SError('Both "stage" and "region" params are required'); // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Function could not be populated because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Function could not be populated because no project path has been set on Serverless instance'); // Populate let clone = _this.get(); @@ -291,7 +290,7 @@ class ServerlessFunction { return new BbPromise.try(function() { // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Function could not be saved because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Function could not be saved because no project path has been set on Serverless instance'); // Create if does not exist if (!SUtils.fileExistsSync(path.join(_this._config.fullPath, 's-function.json'))) { @@ -382,7 +381,7 @@ class ServerlessFunction { */ getProject() { - return this._S.state.project; + return this._S.getProject(); } /** diff --git a/lib/ServerlessMeta.js b/lib/ServerlessMeta.js index af4a3c8f3..e956f8797 100644 --- a/lib/ServerlessMeta.js +++ b/lib/ServerlessMeta.js @@ -16,7 +16,6 @@ class ServerlessMeta /** * Constructor - * - options.projectPath: absolute path to project */ constructor(Serverless) { @@ -40,16 +39,16 @@ class ServerlessMeta return BbPromise.try(function() { // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('No project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('No project path has been set on Serverless instance'); // Validate: Check variables exist - if (SUtils.dirExistsSync(path.join(_this._S.config.projectPath, '_meta', 'variables'))) { + if (SUtils.dirExistsSync(this._S.getProject().getFilePath('_meta', 'variables'))) { - let variableFiles = fs.readdirSync(path.join(_this._S.config.projectPath, '_meta', 'variables')); + let variableFiles = fs.readdirSync(this._S.getProject().getFilePath('_meta', 'variables')); for (let i = 0; i < variableFiles.length; i++) { - let variableFile = SUtils.readAndParseJsonSync(path.join(_this._S.config.projectPath, '_meta', 'variables', variableFiles[i])); + let variableFile = SUtils.readAndParseJsonSync(this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])); // Parse file name to get stage/region let file = variableFiles[i].replace('s-variables-', '').replace('.json', ''); @@ -57,7 +56,7 @@ class ServerlessMeta if (file === 'common') { // Set Common variables - _this.variables = SUtils.readAndParseJsonSync(path.join(_this._S.config.projectPath, '_meta', 'variables', variableFiles[i])); + _this.variables = SUtils.readAndParseJsonSync(this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])); } else { @@ -71,7 +70,7 @@ class ServerlessMeta if (file.length === 1) { // Set Stage Variables - _this.stages[file[0]].variables = SUtils.readAndParseJsonSync(path.join(_this._S.config.projectPath, '_meta', 'variables', variableFiles[i])); + _this.stages[file[0]].variables = SUtils.readAndParseJsonSync(this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])); } else if (file.length === 2) { @@ -82,7 +81,7 @@ class ServerlessMeta if (file[1] === 'euwest1') region = 'eu-west-1'; if (file[1] === 'apnortheast1') region = 'ap-northeast-1'; if (!_this.stages[file[0]].regions[region]) _this.stages[file[0]].regions[region] = { - variables: SUtils.readAndParseJsonSync(path.join(_this._S.config.projectPath, '_meta', 'variables', variableFiles[i])) + variables: SUtils.readAndParseJsonSync(this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])) }; } } @@ -151,25 +150,25 @@ class ServerlessMeta return BbPromise.try(function() { // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Meta could not be saved because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Meta could not be saved because no project path has been set on Serverless instance'); // Create meta folder if does not exist - if (!SUtils.dirExistsSync(path.join(_this._S.config.projectPath, '_meta'))) { - fs.mkdirSync(path.join(_this._S.config.projectPath, '_meta')); + if (!SUtils.dirExistsSync(this._S.getProject().getFilePath('_meta'))) { + fs.mkdirSync(this._S.getProject().getFilePath('_meta')); } // Create meta/resources folder, if does not exist - if (!SUtils.dirExistsSync(path.join(_this._S.config.projectPath, '_meta', 'resources'))) { - fs.mkdirSync(path.join(_this._S.config.projectPath, '_meta', 'resources')); + if (!SUtils.dirExistsSync(this._S.getProject().getFilePath('_meta', 'resources'))) { + fs.mkdirSync(this._S.getProject().getFilePath('_meta', 'resources')); } // Create meta/variables folder, if does not exist - if (!SUtils.dirExistsSync(path.join(_this._S.config.projectPath, '_meta', 'variables'))) { - fs.mkdirSync(path.join(_this._S.config.projectPath, '_meta', 'variables')); + if (!SUtils.dirExistsSync(this._S.getProject().getFilePath('_meta', 'variables'))) { + fs.mkdirSync(this._S.getProject().getFilePath('_meta', 'variables')); } // Save Common Variables - fs.writeFileSync(path.join(_this._S.config.projectPath, '_meta', 'variables', 's-variables-common.json'), + fs.writeFileSync(this._S.getProject().getFilePath('_meta', 'variables', 's-variables-common.json'), JSON.stringify(clone.variables, null, 2)); // Save Stage & Region Variables @@ -178,12 +177,12 @@ class ServerlessMeta let stage = clone.stages[Object.keys(clone.stages)[i]]; // Save Stage Variables - fs.writeFileSync(path.join(_this._S.config.projectPath, '_meta', 'variables', 's-variables-' + Object.keys(clone.stages)[i] + '.json'), + fs.writeFileSync(this._S.getProject().getFilePath('_meta', 'variables', 's-variables-' + Object.keys(clone.stages)[i] + '.json'), JSON.stringify(stage.variables, null, 2)); // Save Stage Region Variables for (let j = 0; j < Object.keys(stage.regions).length; j++) { - fs.writeFileSync(path.join(_this._S.config.projectPath, '_meta', 'variables', 's-variables-' + Object.keys(clone.stages)[i] + '-' + Object.keys(stage.regions)[j].replace(/-/g, '') + '.json'), + fs.writeFileSync(this._S.getProject().getFilePath('_meta', 'variables', 's-variables-' + Object.keys(clone.stages)[i] + '-' + Object.keys(stage.regions)[j].replace(/-/g, '') + '.json'), JSON.stringify(stage.regions[Object.keys(stage.regions)[j]].variables, null, 2)); } } diff --git a/lib/ServerlessProject.js b/lib/ServerlessProject.js index 0cb3b9dce..aa2f72029 100644 --- a/lib/ServerlessProject.js +++ b/lib/ServerlessProject.js @@ -19,10 +19,11 @@ class ServerlessProject { * Constructor */ - constructor(Serverless) { + constructor(rootPath) { let _this = this; - this._S = Serverless; + + _this.rootPath = rootPath; // Default properties _this.name = 'serverless' + SUtils.generateShortId(6); @@ -35,6 +36,56 @@ class ServerlessProject { _this.components = {}; _this.templates = {}; _this.plugins = []; + + _this.load(); + } + + //TODO: get rid of this? + setServerless( Serverless ) { + this._S = Serverless; + } + + static findProject( startDir ){ + let jsonName = 's-project.json'; + + // Check up to 10 parent levels + let previous = '.', + project = undefined, + i = 10; + + while( i >= 0 ) { + let fullPath = path.resolve(startDir, previous); + + if (SUtils.fileExistsSync(path.join(fullPath, jsonName))) { + let projectJson = require(path.join(fullPath, jsonName)); + if (typeof projectJson.name !== 'undefined') { + project = new ServerlessProject( fullPath ); + break; + } + } + + previous = path.join(previous, '..'); + } + + return project; + } + + getPlugins(){ + return this.plugins; + } + + getRootPath(){ + return this.rootPath; + } + + getFilePath(){ + let args = _.toArray( arguments ); + args.unshift( this.getRootPath() ); + return path.apply( path, args ); + } + + getName(){ + return this.name; } /** @@ -50,19 +101,15 @@ class ServerlessProject { projectContents; return BbPromise.try(function () { - - // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Project could not be loaded because no project path has been set on Serverless instance'); - // Validate: Check project exists - if (!SUtils.fileExistsSync(path.join(_this._S.config.projectPath, 's-project.json'))) { + if (!SUtils.fileExistsSync(_this.getFilePath('s-project.json'))) { throw new SError('Project could not be loaded because it does not exist'); } - projectJson = SUtils.readAndParseJsonSync(path.join(_this._S.config.projectPath, 's-project.json')); + projectJson = SUtils.readAndParseJsonSync(_this.getFilePath('s-project.json')); projectJson.components = {}; projectJson.templates = {}; - projectContents = fs.readdirSync(_this._S.config.projectPath); + projectContents = fs.readdirSync(_this.getRootPath()); return projectContents; }) @@ -70,12 +117,12 @@ class ServerlessProject { // If template, load template if (c.indexOf('s-template') !== -1) { - projectJson.templates = _.assign(projectJson.templates, SUtils.readAndParseJsonSync(path.join(_this._S.config.projectPath, c))); + projectJson.templates = _.assign(projectJson.templates, SUtils.readAndParseJsonSync(_this.getFilePath(c))); return; } // If component, load component - if (SUtils.fileExistsSync(path.join(_this._S.config.projectPath, c, 's-component.json'))) { + if (SUtils.fileExistsSync(_this.getFilePath(c, 's-component.json'))) { let component = new _this._S.classes.Component(_this._S, { sPath: c @@ -150,9 +197,6 @@ class ServerlessProject { // Validate: Check Stage & Region if (!options.stage || !options.region) throw new SError('Both "stage" and "region" params are required'); - // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Project could not be populated because no project path has been set on Serverless instance'); - // Populate components let clone = _this.get(); clone = SUtils.populate(_this._S.state.getMeta(), _this.getTemplates(), clone, options.stage, options.region); @@ -185,8 +229,8 @@ class ServerlessProject { options = options || {}; // Check for s-resources-cf.json - if (SUtils.fileExistsSync(path.join(_this._S.config.projectPath, 's-resources-cf.json'))) { - resources = SUtils.readAndParseJsonSync(path.join(_this._S.config.projectPath, 's-resources-cf.json')); + if (SUtils.fileExistsSync(_this.getFilePath('s-resources-cf.json'))) { + resources = SUtils.readAndParseJsonSync(_this.getFilePath('s-resources-cf.json')); if (options.populate) { return BbPromise.resolve(SUtils.populate(_this._S.state.getMeta(), _this.getTemplates(), resources, options.stage, options.region)); @@ -273,14 +317,11 @@ class ServerlessProject { let _this = this, files = []; - // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Project could not be saved because no project path has been set on Serverless instance'); - return new BbPromise.try(function () { // If project folder does not exist, create it - if (!SUtils.dirExistsSync(path.join(_this._S.config.projectPath))) { - fs.mkdirSync(path.join(_this._S.config.projectPath)); + if (!SUtils.dirExistsSync(_this.getRootPath())) { + fs.mkdirSync(_this.getRootPath()); } // Save all nested components @@ -302,7 +343,7 @@ class ServerlessProject { if (clone.templates) delete clone.templates; // Save s-project.json - files.push(SUtils.writeFile(path.join(_this._S.config.projectPath, 's-project.json'), + files.push(SUtils.writeFile(_this.getFilePath('s-project.json'), JSON.stringify(clone, null, 2))); // Write files diff --git a/lib/ServerlessState.js b/lib/ServerlessState.js index 9cf45ccf9..8b8a69b90 100644 --- a/lib/ServerlessState.js +++ b/lib/ServerlessState.js @@ -34,7 +34,7 @@ class ServerlessState { let _this = this; - return _this.project.load() + return _this.S.getProject().load() .then(function() { return _this.meta.load(); }); @@ -49,7 +49,7 @@ class ServerlessState { let _this = this; - return _this.project.save({ deep: true }) + return _this.S.getProject().save({ deep: true }) .then(function() { return _this.meta.save({ deep: true }); }); @@ -62,25 +62,23 @@ class ServerlessState { set(data) { this.meta = data.meta ? this.meta.set(data.meta) : this.meta; - this.project = data.project ? this.project.set(data.project, { deep: true }) : this.project; + this.project = data.project ? this.S.getProject().set(data.project, { deep: true }) : this.S.getProject(); return this; } /** * Set Asset * - Add or replace an asset to the state - * - Accepts a class instance of: Project, Component, Function, Endpoint + * - Accepts a class instance of: Component, Function, Endpoint */ setAsset(data) { - if (data instanceof this._S.classes.Project) { - this.project = data; - } else if (data instanceof this._S.classes.Component) { - this.project.components[data.name] = data; + if (data instanceof this._S.classes.Component) { + this.S.getProject().components[data.name] = data; } else if (data instanceof this._S.classes.Function) { - this.project.components[data._config.sPath.split('/')[0]].functions[data._config.sPath] = data; + this.S.getProject().components[data._config.sPath.split('/')[0]].functions[data._config.sPath] = data; } else if (data instanceof this._S.classes.Endpoint) { - let func = this.project.components[data._config.sPath.split('/')[0]].functions[data._config.sPath.split('@')[0]]; + let func = this.S.getProject().components[data._config.sPath.split('/')[0]].functions[data._config.sPath.split('@')[0]]; let added = false; for (let i = 0; i < func.endpoints.length; i++) { if (func.endpoints[i].path === data.path && func.endpoints[i].method === data.method) { @@ -90,7 +88,7 @@ class ServerlessState { } if (!added) func.endpoints.push(data); } else { - return new SError('State.setAsset() failed because you did not submit an instance of a Project, Component, Function or Endpoint class.'); + return new SError('State.setAsset() failed because you did not submit an instance of a Component, Function or Endpoint class.'); } } @@ -102,7 +100,7 @@ class ServerlessState { get() { return { meta: this.meta.get(), - project: this.project.get() + project: this.S.getProject().get() } } @@ -120,7 +118,7 @@ class ServerlessState { return { meta: this.meta.get(), - project: this.project.getPopulated(options) + project: this.S.getProject().getPopulated(options) } } @@ -139,7 +137,7 @@ class ServerlessState { */ getProject() { - return this.project; + return this.S.getProject(); } /** @@ -148,7 +146,7 @@ class ServerlessState { */ getResources(options) { - return this.project.getResources(options); + return this.S.getProject().getResources(options); } /** @@ -183,8 +181,8 @@ class ServerlessState { foundComponents = []; // Get all - for (let i = 0; i < Object.keys(_this.project.components).length; i++) { - allComponents.push(_this.project.components[Object.keys(_this.project.components)[i]]); + for (let i = 0; i < Object.keys(_this.S.getProject().components).length; i++) { + allComponents.push(_this.S.getProject().components[Object.keys(_this.S.getProject().components)[i]]); } // Return if no options specified @@ -227,8 +225,8 @@ class ServerlessState { foundFunctions = []; // Get all - for (let i = 0; i < Object.keys(_this.project.components).length; i++) { - let component = _this.project.components[Object.keys(_this.project.components)[i]]; + for (let i = 0; i < Object.keys(_this.S.getProject().components).length; i++) { + let component = _this.S.getProject().components[Object.keys(_this.S.getProject().components)[i]]; for (let j = 0; j < Object.keys(component.functions).length; j++) { allFunctions.push(component.functions[Object.keys(component.functions)[j]]); } @@ -275,8 +273,8 @@ class ServerlessState { foundEndpoints = []; // Get all functions - for (let i = 0; i < Object.keys(_this.project.components).length; i++) { - let component = _this.project.components[Object.keys(_this.project.components)[i]]; + for (let i = 0; i < Object.keys(_this.S.getProject().components).length; i++) { + let component = _this.S.getProject().components[Object.keys(_this.S.getProject().components)[i]]; if (!component.functions) continue; for (let k = 0; k < Object.keys(component.functions).length; k++) { let func = component.functions[Object.keys(component.functions)[k]]; diff --git a/lib/actions/CodePackageLambda.js b/lib/actions/CodePackageLambda.js index 792a6353d..ca74da297 100644 --- a/lib/actions/CodePackageLambda.js +++ b/lib/actions/CodePackageLambda.js @@ -140,7 +140,7 @@ module.exports = function(SPlugin, serverlessPath) { // Set Dist Dir let d = new Date(); - _this.pathDist = path.join(_this.S.config.projectPath, '_meta', '_tmp', _this.function.name + '@' + d.getTime()); + _this.pathDist = _this.S.getProject().getFilePath('_meta', '_tmp', _this.function.name + '@' + d.getTime()); // Status SUtils.sDebug(`"${_this.evt.options.stage} - ${_this.evt.options.region} - ${_this.function.name}": Copying in dist dir ${_this.pathDist}`); diff --git a/lib/actions/ComponentCreate.js b/lib/actions/ComponentCreate.js index e5694296e..9b9053b71 100644 --- a/lib/actions/ComponentCreate.js +++ b/lib/actions/ComponentCreate.js @@ -152,7 +152,7 @@ usage: serverless component create`, } // If component exists in project, throw error - if (SUtils.doesComponentExist(this.evt.options.sPath, this.S.config.projectPath)) { + if (SUtils.doesComponentExist(this.evt.options.sPath, this.S.getProject().getRootPath())) { return BbPromise.reject(new SError( 'Component ' + this.evt.options.sPath + ' already exists', SError.errorCodes.INVALID_PROJECT_SERVERLESS @@ -185,14 +185,14 @@ usage: serverless component create`, if (_this.evt.options.runtime === 'nodejs') { SCli.log('Installing "serverless-helpers" for this component via NPM...'); SCli.log(`-----------------`); - SUtils.npmInstall(path.join(this.S.config.projectPath, this.evt.options.sPath)); + SUtils.npmInstall(this.S.getProject().getFilePath(this.evt.options.sPath)); SCli.log(`-----------------`); } else if (_this.evt.options.runtime === 'python2.7') { SCli.log("Installing default python dependencies with pip..."); SCli.log(`-----------------`); SUtils.pipPrefixInstall( - path.join(this.S.config.projectPath, this.evt.options.sPath, 'requirements.txt'), - path.join(this.S.config.projectPath, this.evt.options.sPath, 'vendored') + path.join(this.S.getProject().getFilePath(this.evt.options.sPath, 'requirements.txt'), + path.join(this.S.getProject().getFilePath(this.evt.options.sPath, 'vendored') ); SCli.log(`-----------------`); } diff --git a/lib/actions/DashDeploy.js b/lib/actions/DashDeploy.js index 24963b257..11e38f64e 100644 --- a/lib/actions/DashDeploy.js +++ b/lib/actions/DashDeploy.js @@ -150,7 +150,7 @@ module.exports = function(SPlugin, serverlessPath) { } // Get all functions in CWD - let sPath = _this.getSPathFromCwd(_this.S.config.projectPath); + let sPath = _this.getSPathFromCwd(_this.S.getProject().getRootPath()); _this.components = _this.S.state.getComponents({ paths: sPath ? [sPath] : [] diff --git a/lib/actions/EndpointDeploy.js b/lib/actions/EndpointDeploy.js index d1943a438..f8af94c4f 100644 --- a/lib/actions/EndpointDeploy.js +++ b/lib/actions/EndpointDeploy.js @@ -174,7 +174,7 @@ module.exports = function(SPlugin, serverlessPath) { !_this.evt.options.all) { // Get all functions in CWD - let sPath = _this.getSPathFromCwd(_this.S.config.projectPath); + let sPath = _this.getSPathFromCwd(_this.S.getProject().getRootPath()); if (!sPath) { throw new SError(`You must be in a component to deploy. Otherwise, use the command "serverless dash deploy"`); diff --git a/lib/actions/EnvSet.js b/lib/actions/EnvSet.js index afba66b8f..1e7408b00 100644 --- a/lib/actions/EnvSet.js +++ b/lib/actions/EnvSet.js @@ -185,7 +185,7 @@ usage: serverless env set`, }); if (_this.evt.options.stage == 'local') { - putEnvQ.push(SUtils.writeFile(path.join(this.S.config.projectPath, '.env'), contents)); + putEnvQ.push(SUtils.writeFile(this.S.getProject().getFilePath('.env'), contents)); } else { let projectName = _this.S.state.meta.get().variables.project, bucketName = _this.S.state.meta.get().variables.projectBucket, diff --git a/lib/actions/EnvUnset.js b/lib/actions/EnvUnset.js index 74e68d172..6991dd8f8 100644 --- a/lib/actions/EnvUnset.js +++ b/lib/actions/EnvUnset.js @@ -176,7 +176,7 @@ usage: serverless env unset`, }); if (_this.evt.options.stage == 'local') { - putEnvQ.push(SUtils.writeFile(path.join(_this.S.config.projectPath, '.env'), contents)); + putEnvQ.push(SUtils.writeFile(_this.S.getProject().getFilePath('.env'), contents)); } else { let projectName = _this.S.state.meta.get().variables.project, bucketName = _this.S.state.meta.get().variables.projectBucket, diff --git a/lib/actions/FunctionCreate.js b/lib/actions/FunctionCreate.js index f2b89c354..2cb711ddf 100644 --- a/lib/actions/FunctionCreate.js +++ b/lib/actions/FunctionCreate.js @@ -93,7 +93,7 @@ usage: serverless function create `, if (!_this.S.config.interactive || _this.evt.options.sPath) return BbPromise.resolve(); // Get sPath - _this.evt.options.sPath = _this.getSPathFromCwd(_this.S.config.projectPath); + _this.evt.options.sPath = _this.getSPathFromCwd(_this.S.getProject().getRootPath()); // Validate if (!_this.evt.options.sPath) { @@ -129,7 +129,7 @@ usage: serverless function create `, // Validate: If interactive and no sPath, check they are in a component, and get sPath if (_this.S.config.interactive && !_this.evt.options.sPath) { - _this.evt.options.sPath = _this.getSPathFromCwd(_this.S.config.projectPath); + _this.evt.options.sPath = _this.getSPathFromCwd(_this.S.getProject().getRootPath()); if (!_this.evt.options.sPath) { return BbPromise.reject(new SError('You must be in a component or two subfolders max in a component to create a function')); } @@ -163,11 +163,11 @@ usage: serverless function create `, let dir = _this.evt.options.sPath.split('/'); dir.pop(); let c = dir.shift(); - if (dir[0] && !SUtils.dirExistsSync(path.join(_this.S.config.projectPath, c, dir[0]))) { - fs.mkdirSync(path.join(_this.S.config.projectPath, c, dir[0])); + if (dir[0] && !SUtils.dirExistsSync(_this.S.project.getFilePath(c, dir[0]))) { + fs.mkdirSync(_this.S.project.getFilePath(c, dir[0])); } - if (dir[1] && !SUtils.dirExistsSync(path.join(_this.S.config.projectPath, c, dir[0], dir[1]))) { - fs.mkdirSync(path.join(_this.S.config.projectPath, c, dir[0], dir[1])); + if (dir[1] && !SUtils.dirExistsSync(_this.S.project.getFilePath(c, dir[0], dir[1]))) { + fs.mkdirSync(_this.S.project.getFilePath(c, dir[0], dir[1])); } } diff --git a/lib/actions/FunctionDeploy.js b/lib/actions/FunctionDeploy.js index ee6d24d6d..459cb67d8 100644 --- a/lib/actions/FunctionDeploy.js +++ b/lib/actions/FunctionDeploy.js @@ -187,7 +187,7 @@ module.exports = function(SPlugin, serverlessPath) { !_this.evt.options.all) { // Get all functions in CWD - let sPath = _this.getSPathFromCwd(_this.S.config.projectPath); + let sPath = _this.getSPathFromCwd(_this.S.getProject().getRootPath()); if (!sPath) { throw new SError(`You must be in a component or function folder to deploy. Otherwise, use the command "serverless dash deploy"`); @@ -211,8 +211,8 @@ module.exports = function(SPlugin, serverlessPath) { } // Ensure tmp folder exists in _meta - if (!SUtils.dirExistsSync(path.join(_this.S.config.projectPath, '_meta', '_tmp'))) { - fs.mkdirSync(path.join(_this.S.config.projectPath, '_meta', '_tmp')); + if (!SUtils.dirExistsSync(_this.S.project.getFilePath('_meta', '_tmp'))) { + fs.mkdirSync(_this.S.project.getFilePath('_meta', '_tmp')); } return BbPromise.resolve(); diff --git a/lib/actions/FunctionLogs.js b/lib/actions/FunctionLogs.js index ac535c71e..61591737c 100644 --- a/lib/actions/FunctionLogs.js +++ b/lib/actions/FunctionLogs.js @@ -111,7 +111,7 @@ module.exports = function(SPlugin, serverlessPath) { // If CLI and path is not specified, deploy from CWD if Function if (this.S.cli && !this.evt.options.path) { // Get all functions in CWD - let sPath = this.getSPathFromCwd(this.S.config.projectPath); + let sPath = this.getSPathFromCwd(this.S.getProject().getRootPath()); if (!sPath) { throw new SError(`You must be in a function folder to run it`); } diff --git a/lib/actions/FunctionRun.js b/lib/actions/FunctionRun.js index 832662baa..79b63bf13 100644 --- a/lib/actions/FunctionRun.js +++ b/lib/actions/FunctionRun.js @@ -102,12 +102,12 @@ module.exports = function(SPlugin, serverlessPath) { let _this = this; // Instantiate Classes - _this.project = _this.S.state.project.get(); + _this.project = _this.S.getProject().get(); // If CLI and path is not specified, deploy from CWD if Function if (_this.S.cli && !_this.evt.options.path) { // Get all functions in CWD - let sPath = _this.getSPathFromCwd(_this.S.config.projectPath); + let sPath = _this.getSPathFromCwd(_this.S.getProject().getRootPath()); if (!sPath || sPath.split('/').length == 1) { return BbPromise.reject(new SError(`You must be in a function folder to run it`)); } diff --git a/lib/actions/ModuleInstall.js b/lib/actions/ModuleInstall.js index 8a677014b..49a7495ed 100644 --- a/lib/actions/ModuleInstall.js +++ b/lib/actions/ModuleInstall.js @@ -173,10 +173,10 @@ usage: serverless module install `, } _this.evt.data.module = srcModuleJson.name; - _this.pathModule = path.join(this.S.config.projectPath, 'back', 'modules', _this.evt.data.module); + _this.pathModule = _this.S.project.getFilePath('back', 'modules', _this.evt.data.module); // if same module name exists, throw error - if (SUtils.doesModuleExist(srcModuleJson.name, this.S.config.projectPath)) { + if (SUtils.doesModuleExist(srcModuleJson.name, this.S.getProject().getRootPath())) { return BbPromise.reject(new SError( 'Module ' + _this.evt.data.module + ' already exists', SError.errorCodes.INVALID_PROJECT_SERVERLESS diff --git a/lib/actions/ProjectInit.js b/lib/actions/ProjectInit.js index 40d186291..52c01dce0 100644 --- a/lib/actions/ProjectInit.js +++ b/lib/actions/ProjectInit.js @@ -128,7 +128,6 @@ module.exports = function(SPlugin, serverlessPath) { * Return EVT */ - _this.evt.data.projectPath = _this.S.config.projectPath; return _this.evt; }); } @@ -145,15 +144,11 @@ module.exports = function(SPlugin, serverlessPath) { // fixes the double generated domain id bug if (_this.evt.options.name) isName = true; - // Check if s-project.json exists - if (_this.S.config.projectPath && SUtils.fileExistsSync(path.join(_this.S.config.projectPath, 's-project.json'))) { - + // Check if project exists + if (_this.S.getProject()) { // Set temp name - let projectJson = SUtils.readAndParseJsonSync(path.join(_this.S.config.projectPath, 's-project.json')); - name = _this.evt.options.name ? _this.evt.options.name : (projectJson.name + '-' + SUtils.generateShortId(6)).toLowerCase(); - + name = _this.evt.options.name ? _this.evt.options.name : (_this.S.getProject().getName() + '-' + SUtils.generateShortId(6)).toLowerCase(); } else { - // Set temp name name = _this.evt.options.name ? _this.evt.options.name : ('serverless-' + SUtils.generateShortId(6)).toLowerCase(); } @@ -351,10 +346,9 @@ module.exports = function(SPlugin, serverlessPath) { return BbPromise.try(function() { // Update Global Serverless Instance - if (!_this.S.config.projectPath) { - _this.S.updateConfig({ - projectPath: path.resolve(path.join(path.dirname('.'), _this.evt.options.name)) - }); + if( !_this.S.hasProject() ) { + let projectPath = path.resolve(path.join(path.dirname('.'), _this.evt.options.name)); + _this.S.setProject( new _this.S.classes.Project( projectPath ) ); } // Fill in meta attributes @@ -365,18 +359,15 @@ module.exports = function(SPlugin, serverlessPath) { _this.meta.variables.notificationEmail = _this.evt.options.notificationEmail; // Fill in project attributes - _this.project = _this.S.state.getProject(); + _this.project = _this.S.getProject(); _this.project.name = _this.evt.options.name; // Create s-resources-cf.json if (!_this.project.cloudFormation && // In case initializing older project w/ cloudFormation property - !SUtils.fileExistsSync( - path.join( - _this.S.config.projectPath, - 's-resources-cf.json'))) { + !SUtils.fileExistsSync( _.this.project.getFilePath( 's-resources-cf.json' ))) { files.push( SUtils.writeFile( - path.join(_this.S.config.projectPath, 's-resources-cf.json'), + _this.project.getFilePath( 's-resources-cf.json' ) ), JSON.stringify( SUtils.readAndParseJsonSync(path.join(_this.S.config.serverlessPath, 'templates', 's-resources-cf.json')), null, 2) @@ -394,31 +385,31 @@ module.exports = function(SPlugin, serverlessPath) { // Create other scaffolding // If admin.env does not exist, save it - if (!SUtils.fileExistsSync(path.join(_this.S.config.projectPath, 'admin.env'))) { + if (!SUtils.fileExistsSync(_this.project.getFilePath( 'admin.env' ))) { let adminEnv = 'SERVERLESS_ADMIN_AWS_ACCESS_KEY_ID=' + _this.S.config.awsAdminKeyId + os.EOL + 'SERVERLESS_ADMIN_AWS_SECRET_ACCESS_KEY=' + _this.S.config.awsAdminSecretKey + os.EOL; - files.push(fs.writeFileAsync(path.join(_this.S.config.projectPath, 'admin.env'), adminEnv)); + files.push(fs.writeFileAsync(_this.project.getFilePath( 'admin.env' ), adminEnv)); } // If package.json does not exist, save it let packageJson; - if (!SUtils.fileExistsSync(path.join(_this.S.config.projectPath, 'package.json'))) { + if (!SUtils.fileExistsSync(_this.project.getFilePath( 'package.json' ))) { // Prepare new package.json packageJson = SUtils.readAndParseJsonSync(path.join(_this.S.config.serverlessPath, 'templates', 'nodejs', 'package.json')); - packageJson.name = _this.project.name; + packageJson.name = _this.project.getName(); packageJson.description = 'A Serverless Project and its Serverless Plugin dependencies.'; packageJson.private = false; packageJson.dependencies = {}; if (packageJson.devDependencies) delete packageJson.devDependencies; if (packageJson.keywords) delete packageJson.keywords; - files.push(fs.writeFileAsync(path.join(_this.S.config.projectPath, 'package.json'), JSON.stringify(packageJson, null, 2))) + files.push(fs.writeFileAsync(_this.project.getFilePath( 'package.json' ), JSON.stringify(packageJson, null, 2))) } else { // Modify existing package.json - packageJson = SUtils.readAndParseJsonSync(path.join(_this.S.config.projectPath, 'package.json')); - packageJson.name = _this.project.name; + packageJson = SUtils.readAndParseJsonSync(_this.project.getFilePath( 'package.json' )); + packageJson.name = _this.project.getName(); // Delete unnecessary package.json properties, if they exist if (packageJson.readme) delete packageJson.readme; @@ -444,25 +435,25 @@ module.exports = function(SPlugin, serverlessPath) { if (packageJson._shrinkwrap || packageJson._shrinkwrap === null) delete packageJson._shrinkwrap; if (packageJson._spec) delete packageJson._spec; if (packageJson._where) delete packageJson._where; - files.push(fs.writeFileAsync(path.join(_this.S.config.projectPath, 'package.json'), JSON.stringify(packageJson, null, 2))) + files.push(fs.writeFileAsync(_this.project.getFilePath( 'package.json' ), JSON.stringify(packageJson, null, 2))) } // If README.md does not exist, save it - if (!SUtils.fileExistsSync(path.join(_this.S.config.projectPath, 'README.md'))) { + if (!SUtils.fileExistsSync(_this.project.getFilePath( 'README.md' ))) { let readme = '#' + _this.project.name; - files.push(fs.writeFileAsync(path.join(_this.S.config.projectPath, 'README.md'), readme)); + files.push(fs.writeFileAsync(_this.project.getFilePath( 'README.md' ), readme)); } // If .gitignore does not exist, save it - if (!SUtils.fileExistsSync(path.join(_this.S.config.projectPath, '.gitignore'))) { - files.push(fs.writeFileAsync(path.join(_this.S.config.projectPath, '.gitignore'), fs.readFileSync(path.join(_this.S.config.serverlessPath, 'templates', 'gitignore')))); + if (!SUtils.fileExistsSync(_this.project.getFilePath( '.gitignore' ))) { + files.push(fs.writeFileAsync(_this.project.getFilePath( '.gitignore' ), fs.readFileSync(path.join(_this.S.config.serverlessPath, 'templates', 'gitignore')))); } // If .env does not exist, save it - if (!SUtils.fileExistsSync(path.join(_this.S.config.projectPath, '.env'))) { + if (!SUtils.fileExistsSync(_this.project.getFilePath( '.env' ))) { files.push(SUtils.writeFile( - path.join(_this.S.config.projectPath, '.env'), + _this.project.getFilePath( '.env' ), 'SERVERLESS_STAGE=' + _this.evt.options.stage + '\nSERVERLESS_DATA_MODEL_STAGE=' + _this.evt.options.stage + '\nSERVERLESS_PROJECT_NAME=' + _this.project.name @@ -501,11 +492,11 @@ module.exports = function(SPlugin, serverlessPath) { components.forEach(function (component) { SCli.log(`Installing ${component.runtime} dependencies for component: ${component.name}...`); if (component.runtime === 'nodejs') { - SUtils.npmInstall(path.join(_this.S.config.projectPath, component.name)); + SUtils.npmInstall(_this.S.getProject().getFilePath( component.name )); } else if (component.runtime === 'python2.7') { SUtils.pipPrefixInstall( - path.join(_this.S.config.projectPath, component.name, 'requirements.txt'), - path.join(_this.S.config.projectPath, component.name, 'vendored') + _this.S.getProject().getFilePath( component.name, 'requirements.txt' ), + _this.S.getProject().getFilePath( component.name, 'vendored' ) ); } return BbPromise.resolve(); diff --git a/lib/actions/ProjectInstall.js b/lib/actions/ProjectInstall.js index a06d9a019..db97962b2 100644 --- a/lib/actions/ProjectInstall.js +++ b/lib/actions/ProjectInstall.js @@ -208,13 +208,12 @@ module.exports = function(SPlugin, serverlessPath) { let _this = this; // Update Global Serverless Instance - if (!_this.S.config.projectPath) { - _this.S.updateConfig({ - projectPath: path.resolve(path.join(path.dirname('.'), _this.evt.options.name ? _this.evt.options.name : _this.evt.options.project)) - }); + if( !_this.S.hasProject() ) { + let projectPath = path.resolve(path.join(path.dirname('.'), _this.evt.options.name ? _this.evt.options.name : _this.evt.options.project); + _this.S.setProject( new _this.S.classes.Project( projectPath ) ); } - // Load state again now that the projectPath is set + // Load state again now that the project is set return _this.S.state.load() .then(function() { diff --git a/lib/actions/RegionRemove.js b/lib/actions/RegionRemove.js index ede2accc7..1daeea3c7 100644 --- a/lib/actions/RegionRemove.js +++ b/lib/actions/RegionRemove.js @@ -197,7 +197,7 @@ usage: serverless region remove`, _removeVariables() { let fileName = `s-variables-${this.evt.options.stage}-${this.evt.options.region.replace(/-/g, '')}.json`; - return fs.unlinkAsync(path.join(this.S.config.projectPath, '_meta', 'variables', fileName)); + return fs.unlinkAsync(this.S.project.getFilePath('_meta', 'variables', fileName)); } diff --git a/lib/actions/ResourcesDeploy.js b/lib/actions/ResourcesDeploy.js index 5e597a251..f902be5e1 100644 --- a/lib/actions/ResourcesDeploy.js +++ b/lib/actions/ResourcesDeploy.js @@ -167,7 +167,7 @@ usage: serverless resources deploy`, console.log(resources); // Create CloudFormation template in _meta folder return SUtils.writeFile( - path.join(_this.S.config.projectPath, '_meta', 'resources', 's-resources-cf-' + _this.evt.options.stage + '-' + replaceall('-', '', _this.evt.options.region) + '.json'), + _this.S.project.getFilePath('_meta', 'resources', 's-resources-cf-' + _this.evt.options.stage + '-' + replaceall('-', '', _this.evt.options.region) + '.json'), JSON.stringify(_this.cfTemplate, null, 2)) }) @@ -208,7 +208,6 @@ usage: serverless resources deploy`, // Upload to S3 Bucket return _this.S3.sPutCfFile( _this.S.state.getMeta().variables.projectBucket, - _this.S.config.projectPath, _this.S.state.getProject().name, _this.evt.options.stage, _this.evt.options.region, diff --git a/lib/actions/ResourcesRemove.js b/lib/actions/ResourcesRemove.js index c464aa289..1610483d7 100644 --- a/lib/actions/ResourcesRemove.js +++ b/lib/actions/ResourcesRemove.js @@ -159,7 +159,6 @@ usage: serverless resources remove`, region = _this.evt.options.region, regionVars = _this.S.state.getMeta().stages[stage].regions[region].variables, projectBucket = _this.S.state.getMeta().variables.projectBucket, - projectPath = _this.S.config.projectPath, projectName = _this.S.state.getProject().name; // Config AWS Services @@ -184,7 +183,7 @@ usage: serverless resources remove`, let removeLocalResourceFile = function() { let fileName = `s-resources-cf-${stage}-${region.replace(/-/g, '')}.json`; - let resourcesLocalFilePath = path.join(projectPath, '_meta', 'resources', fileName); + let resourcesLocalFilePath = _this.S.project.getFilePath('_meta', 'resources', fileName); if (SUtils.fileExistsSync(resourcesLocalFilePath)) { SUtils.sDebug(`Removing resources file "${fileName}"`); diff --git a/lib/actions/StageRemove.js b/lib/actions/StageRemove.js index 5fab69f91..72031bc91 100644 --- a/lib/actions/StageRemove.js +++ b/lib/actions/StageRemove.js @@ -123,7 +123,7 @@ usage: serverless stage remove`, _removeVariables() { let fileName = `s-variables-${this.evt.options.stage}.json`; - return fs.unlinkAsync(path.join(this.S.config.projectPath, '_meta', 'variables', fileName)); + return fs.unlinkAsync(this.S.project.getFilePath('_meta', 'variables', fileName)); } _removeMeta() { diff --git a/lib/utils/aws/Misc.js b/lib/utils/aws/Misc.js index 9b0b735b7..e13aa72e0 100644 --- a/lib/utils/aws/Misc.js +++ b/lib/utils/aws/Misc.js @@ -121,7 +121,7 @@ module.exports.getEnvFileAsMap = function(Serverless, region, stage) { let deferred; if (stage == 'local') { - deferred = Promise.resolve(fs.readFileSync(path.join(Serverless.config.projectPath, '.env'))); + deferred = Promise.resolve(fs.readFileSync(Serverless.project.getFilePath( '.env' ))); } else { let projectName = Serverless.state.meta.get().variables.project, bucketName = Serverless.state.meta.get().variables.projectBucket, diff --git a/lib/utils/aws/S3.js b/lib/utils/aws/S3.js index 0bf47be13..a3695dd8c 100644 --- a/lib/utils/aws/S3.js +++ b/lib/utils/aws/S3.js @@ -159,13 +159,12 @@ module.exports = function(config) { * Put CF File On S3 */ - S3.sPutCfFile = function(bucketName, projectPath, projectName, stage, region, cfTemplate) { + S3.sPutCfFile = function(bucketName, projectName, stage, region, cfTemplate) { // Set S3 Config To Project Bucket S3.sSetProjectBucketConfig(bucketName); let d = new Date(), - cfPath = path.join(projectPath, 'meta', 'private', 'resources', 's-resources-cf.json'), key = ['serverless', projectName, stage, region, 'resources/' + 's-resources-cf'].join('/') + '@' + d.getTime() + '.json', params = { Bucket: bucketName, diff --git a/lib/utils/index.js b/lib/utils/index.js index f6da13a73..e5ee1b9ae 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -92,42 +92,6 @@ exports.parseSPath = function(sPath) { } }; -/** - * Get Project Path - * - Returns path string - */ - -exports.getProjectPath = function(startDir) { - - let _this = this; - - // Check if startDir is root - if (_this.fileExistsSync(path.join(startDir, 's-project.json'))) { - - let jawsJsonInDir = require(path.join(startDir, 's-project.json')); - if (typeof jawsJsonInDir.name !== 'undefined') return path.resolve(startDir); - } - - // Check up to 10 parent levels - let previous = './', - projRootPath = false; - - for (let i = 0; i < 10; i++) { - previous = path.join(previous, '../'); - let fullPath = path.resolve(startDir, previous); - - if (_this.fileExistsSync(path.join(fullPath, 's-project.json'))) { - let jawsJson = require(path.join(fullPath, 's-project.json')); - if (typeof jawsJson.name !== 'undefined') { - projRootPath = fullPath; - break; - } - } - } - - return projRootPath; -}; - /** * Read Recursively */ diff --git a/tests/tests/actions/ResourcesDeploy.js b/tests/tests/actions/ResourcesDeploy.js index 9c771ffe8..4afa8452d 100644 --- a/tests/tests/actions/ResourcesDeploy.js +++ b/tests/tests/actions/ResourcesDeploy.js @@ -51,7 +51,7 @@ describe('Test action: Resources Deploy', function() { SUtils.sDebug('Adding test bucket resource'); - let newProject = serverless.state.project.get(); + let newProject = serverless.project.get(); // Adding new Module resource newProject.cloudFormation.Resources['testBucket' + (new Date).getTime().toString()] = { "Type" : "AWS::S3::Bucket" }; From 0d55b5449fc54265376700f1b42c4a89cf77b10a Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Tue, 9 Feb 2016 16:27:54 +0100 Subject: [PATCH 03/17] Typos fixed. --- lib/ServerlessEndpoint.js | 2 +- lib/ServerlessFunction.js | 2 +- lib/ServerlessMeta.js | 12 ++++++------ lib/ServerlessProject.js | 2 +- lib/ServerlessState.js | 34 ++++++++++++++++------------------ lib/actions/ComponentCreate.js | 4 ++-- lib/actions/ProjectInit.js | 2 +- lib/actions/ProjectInstall.js | 2 +- 8 files changed, 29 insertions(+), 31 deletions(-) diff --git a/lib/ServerlessEndpoint.js b/lib/ServerlessEndpoint.js index a3b2a33dd..ecb7bbca8 100644 --- a/lib/ServerlessEndpoint.js +++ b/lib/ServerlessEndpoint.js @@ -70,7 +70,7 @@ class ServerlessEndpoint { // Make full path if (this._S.hasProject() && this._config.sPath) { - this._config.fullPath = this._S.getProject().getFilePath( this._config.sPath.split('@')[0].split('/') ); + this._config.fullPath = this._S.getProject().getFilePath( this._config.sPath.split('@')[0].split('/').join(path.sep) ); } } diff --git a/lib/ServerlessFunction.js b/lib/ServerlessFunction.js index 64724b3df..d3b5e3efd 100644 --- a/lib/ServerlessFunction.js +++ b/lib/ServerlessFunction.js @@ -98,7 +98,7 @@ class ServerlessFunction { // Make full path if (this._S.hasProject() && this._config.sPath) { - this._config.fullPath = this._S.getProject().getFilePath( this._config.sPath.split('/') ); + this._config.fullPath = this._S.getProject().getFilePath( this._config.sPath.split('/').join(path.sep) ); } } diff --git a/lib/ServerlessMeta.js b/lib/ServerlessMeta.js index e956f8797..534ed4332 100644 --- a/lib/ServerlessMeta.js +++ b/lib/ServerlessMeta.js @@ -42,13 +42,13 @@ class ServerlessMeta if (!_this._S.hasProject()) throw new SError('No project path has been set on Serverless instance'); // Validate: Check variables exist - if (SUtils.dirExistsSync(this._S.getProject().getFilePath('_meta', 'variables'))) { + if (SUtils.dirExistsSync(_this._S.getProject().getFilePath('_meta', 'variables'))) { - let variableFiles = fs.readdirSync(this._S.getProject().getFilePath('_meta', 'variables')); + let variableFiles = fs.readdirSync(_this._S.getProject().getFilePath('_meta', 'variables')); for (let i = 0; i < variableFiles.length; i++) { - let variableFile = SUtils.readAndParseJsonSync(this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])); + let variableFile = SUtils.readAndParseJsonSync(_this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])); // Parse file name to get stage/region let file = variableFiles[i].replace('s-variables-', '').replace('.json', ''); @@ -56,7 +56,7 @@ class ServerlessMeta if (file === 'common') { // Set Common variables - _this.variables = SUtils.readAndParseJsonSync(this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])); + _this.variables = SUtils.readAndParseJsonSync(_this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])); } else { @@ -70,7 +70,7 @@ class ServerlessMeta if (file.length === 1) { // Set Stage Variables - _this.stages[file[0]].variables = SUtils.readAndParseJsonSync(this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])); + _this.stages[file[0]].variables = SUtils.readAndParseJsonSync(_this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])); } else if (file.length === 2) { @@ -81,7 +81,7 @@ class ServerlessMeta if (file[1] === 'euwest1') region = 'eu-west-1'; if (file[1] === 'apnortheast1') region = 'ap-northeast-1'; if (!_this.stages[file[0]].regions[region]) _this.stages[file[0]].regions[region] = { - variables: SUtils.readAndParseJsonSync(this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])) + variables: SUtils.readAndParseJsonSync(_this._S.getProject().getFilePath('_meta', 'variables', variableFiles[i])) }; } } diff --git a/lib/ServerlessProject.js b/lib/ServerlessProject.js index aa2f72029..be9682d9d 100644 --- a/lib/ServerlessProject.js +++ b/lib/ServerlessProject.js @@ -81,7 +81,7 @@ class ServerlessProject { getFilePath(){ let args = _.toArray( arguments ); args.unshift( this.getRootPath() ); - return path.apply( path, args ); + return path.join.apply( path, args ); } getName(){ diff --git a/lib/ServerlessState.js b/lib/ServerlessState.js index 8b8a69b90..e0ed203f1 100644 --- a/lib/ServerlessState.js +++ b/lib/ServerlessState.js @@ -20,8 +20,6 @@ class ServerlessState { this._S = Serverless; this.meta = new this._S.classes.Meta(this._S); - this.project = new this._S.classes.Project(this._S); - } /** @@ -34,7 +32,7 @@ class ServerlessState { let _this = this; - return _this.S.getProject().load() + return _this._S.getProject().load() .then(function() { return _this.meta.load(); }); @@ -49,7 +47,7 @@ class ServerlessState { let _this = this; - return _this.S.getProject().save({ deep: true }) + return _this._S.getProject().save({ deep: true }) .then(function() { return _this.meta.save({ deep: true }); }); @@ -62,7 +60,7 @@ class ServerlessState { set(data) { this.meta = data.meta ? this.meta.set(data.meta) : this.meta; - this.project = data.project ? this.S.getProject().set(data.project, { deep: true }) : this.S.getProject(); + this.project = data.project ? this._S.getProject().set(data.project, { deep: true }) : this._S.getProject(); return this; } @@ -74,11 +72,11 @@ class ServerlessState { setAsset(data) { if (data instanceof this._S.classes.Component) { - this.S.getProject().components[data.name] = data; + this._S.getProject().components[data.name] = data; } else if (data instanceof this._S.classes.Function) { - this.S.getProject().components[data._config.sPath.split('/')[0]].functions[data._config.sPath] = data; + this._S.getProject().components[data._config.sPath.split('/')[0]].functions[data._config.sPath] = data; } else if (data instanceof this._S.classes.Endpoint) { - let func = this.S.getProject().components[data._config.sPath.split('/')[0]].functions[data._config.sPath.split('@')[0]]; + let func = this._S.getProject().components[data._config.sPath.split('/')[0]].functions[data._config.sPath.split('@')[0]]; let added = false; for (let i = 0; i < func.endpoints.length; i++) { if (func.endpoints[i].path === data.path && func.endpoints[i].method === data.method) { @@ -100,7 +98,7 @@ class ServerlessState { get() { return { meta: this.meta.get(), - project: this.S.getProject().get() + project: this._S.getProject().get() } } @@ -118,7 +116,7 @@ class ServerlessState { return { meta: this.meta.get(), - project: this.S.getProject().getPopulated(options) + project: this._S.getProject().getPopulated(options) } } @@ -137,7 +135,7 @@ class ServerlessState { */ getProject() { - return this.S.getProject(); + return this._S.getProject(); } /** @@ -146,7 +144,7 @@ class ServerlessState { */ getResources(options) { - return this.S.getProject().getResources(options); + return this._S.getProject().getResources(options); } /** @@ -181,8 +179,8 @@ class ServerlessState { foundComponents = []; // Get all - for (let i = 0; i < Object.keys(_this.S.getProject().components).length; i++) { - allComponents.push(_this.S.getProject().components[Object.keys(_this.S.getProject().components)[i]]); + for (let i = 0; i < Object.keys(_this._S.getProject().components).length; i++) { + allComponents.push(_this._S.getProject().components[Object.keys(_this._S.getProject().components)[i]]); } // Return if no options specified @@ -225,8 +223,8 @@ class ServerlessState { foundFunctions = []; // Get all - for (let i = 0; i < Object.keys(_this.S.getProject().components).length; i++) { - let component = _this.S.getProject().components[Object.keys(_this.S.getProject().components)[i]]; + for (let i = 0; i < Object.keys(_this._S.getProject().components).length; i++) { + let component = _this._S.getProject().components[Object.keys(_this._S.getProject().components)[i]]; for (let j = 0; j < Object.keys(component.functions).length; j++) { allFunctions.push(component.functions[Object.keys(component.functions)[j]]); } @@ -273,8 +271,8 @@ class ServerlessState { foundEndpoints = []; // Get all functions - for (let i = 0; i < Object.keys(_this.S.getProject().components).length; i++) { - let component = _this.S.getProject().components[Object.keys(_this.S.getProject().components)[i]]; + for (let i = 0; i < Object.keys(_this._S.getProject().components).length; i++) { + let component = _this._S.getProject().components[Object.keys(_this._S.getProject().components)[i]]; if (!component.functions) continue; for (let k = 0; k < Object.keys(component.functions).length; k++) { let func = component.functions[Object.keys(component.functions)[k]]; diff --git a/lib/actions/ComponentCreate.js b/lib/actions/ComponentCreate.js index 9b9053b71..f03f1e599 100644 --- a/lib/actions/ComponentCreate.js +++ b/lib/actions/ComponentCreate.js @@ -191,8 +191,8 @@ usage: serverless component create`, SCli.log("Installing default python dependencies with pip..."); SCli.log(`-----------------`); SUtils.pipPrefixInstall( - path.join(this.S.getProject().getFilePath(this.evt.options.sPath, 'requirements.txt'), - path.join(this.S.getProject().getFilePath(this.evt.options.sPath, 'vendored') + this.S.getProject().getFilePath(this.evt.options.sPath, 'requirements.txt'), + this.S.getProject().getFilePath(this.evt.options.sPath, 'vendored') ); SCli.log(`-----------------`); } diff --git a/lib/actions/ProjectInit.js b/lib/actions/ProjectInit.js index 52c01dce0..372ba28bf 100644 --- a/lib/actions/ProjectInit.js +++ b/lib/actions/ProjectInit.js @@ -367,7 +367,7 @@ module.exports = function(SPlugin, serverlessPath) { !SUtils.fileExistsSync( _.this.project.getFilePath( 's-resources-cf.json' ))) { files.push( SUtils.writeFile( - _this.project.getFilePath( 's-resources-cf.json' ) ), + _this.project.getFilePath( 's-resources-cf.json' ), JSON.stringify( SUtils.readAndParseJsonSync(path.join(_this.S.config.serverlessPath, 'templates', 's-resources-cf.json')), null, 2) diff --git a/lib/actions/ProjectInstall.js b/lib/actions/ProjectInstall.js index db97962b2..06ef686a0 100644 --- a/lib/actions/ProjectInstall.js +++ b/lib/actions/ProjectInstall.js @@ -209,7 +209,7 @@ module.exports = function(SPlugin, serverlessPath) { // Update Global Serverless Instance if( !_this.S.hasProject() ) { - let projectPath = path.resolve(path.join(path.dirname('.'), _this.evt.options.name ? _this.evt.options.name : _this.evt.options.project); + let projectPath = path.resolve(path.join(path.dirname('.'), _this.evt.options.name ? _this.evt.options.name : _this.evt.options.project)); _this.S.setProject( new _this.S.classes.Project( projectPath ) ); } From 4baed3e96f83a513146bf0449e411db234a5b655 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Tue, 9 Feb 2016 16:31:46 +0100 Subject: [PATCH 04/17] Project marked as _project in Serverless class --- lib/Serverless.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Serverless.js b/lib/Serverless.js index d5308cbe6..a6574bfb2 100644 --- a/lib/Serverless.js +++ b/lib/Serverless.js @@ -79,15 +79,15 @@ class Serverless { } getProject() { - return this.project; + return this._project; } hasProject() { - return this.project != undefined; + return this._project != undefined; } setProject( project ) { - this.project = project; + this._project = project; // TODO: get rid of this? Seems like responsibility of Serverless and Project classes is too tangled together project.setServerless( this ); From 7c031bb8ec4920303618d5c248a4f02b4c378b2b Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Tue, 9 Feb 2016 17:29:21 +0100 Subject: [PATCH 05/17] Bugfixes --- lib/Serverless.js | 6 ++++-- lib/ServerlessMeta.js | 18 +++++++++--------- lib/ServerlessProject.js | 4 ++-- lib/actions/EnvSet.js | 4 ++-- lib/actions/FunctionCreate.js | 8 ++++---- lib/actions/FunctionDeploy.js | 4 ++-- lib/actions/ModuleInstall.js | 2 +- lib/actions/ProjectInit.js | 3 ++- lib/actions/ProjectInstall.js | 4 +++- lib/actions/RegionRemove.js | 2 +- lib/actions/ResourcesDeploy.js | 2 +- lib/actions/ResourcesRemove.js | 2 +- lib/actions/StageRemove.js | 2 +- 13 files changed, 33 insertions(+), 28 deletions(-) diff --git a/lib/Serverless.js b/lib/Serverless.js index a6574bfb2..db298c69c 100644 --- a/lib/Serverless.js +++ b/lib/Serverless.js @@ -89,8 +89,10 @@ class Serverless { setProject( project ) { this._project = project; - // TODO: get rid of this? Seems like responsibility of Serverless and Project classes is too tangled together - project.setServerless( this ); + if( project != undefined ){ + // TODO: get rid of this? Seems like responsibility of Serverless and Project classes is too tangled together + project.setServerless( this ); + } } /** diff --git a/lib/ServerlessMeta.js b/lib/ServerlessMeta.js index 534ed4332..f05c1442a 100644 --- a/lib/ServerlessMeta.js +++ b/lib/ServerlessMeta.js @@ -153,22 +153,22 @@ class ServerlessMeta if (!_this._S.hasProject()) throw new SError('Meta could not be saved because no project path has been set on Serverless instance'); // Create meta folder if does not exist - if (!SUtils.dirExistsSync(this._S.getProject().getFilePath('_meta'))) { - fs.mkdirSync(this._S.getProject().getFilePath('_meta')); + if (!SUtils.dirExistsSync(_this._S.getProject().getFilePath('_meta'))) { + fs.mkdirSync(_this._S.getProject().getFilePath('_meta')); } // Create meta/resources folder, if does not exist - if (!SUtils.dirExistsSync(this._S.getProject().getFilePath('_meta', 'resources'))) { - fs.mkdirSync(this._S.getProject().getFilePath('_meta', 'resources')); + if (!SUtils.dirExistsSync(_this._S.getProject().getFilePath('_meta', 'resources'))) { + fs.mkdirSync(_this._S.getProject().getFilePath('_meta', 'resources')); } // Create meta/variables folder, if does not exist - if (!SUtils.dirExistsSync(this._S.getProject().getFilePath('_meta', 'variables'))) { - fs.mkdirSync(this._S.getProject().getFilePath('_meta', 'variables')); + if (!SUtils.dirExistsSync(_this._S.getProject().getFilePath('_meta', 'variables'))) { + fs.mkdirSync(_this._S.getProject().getFilePath('_meta', 'variables')); } // Save Common Variables - fs.writeFileSync(this._S.getProject().getFilePath('_meta', 'variables', 's-variables-common.json'), + fs.writeFileSync(_this._S.getProject().getFilePath('_meta', 'variables', 's-variables-common.json'), JSON.stringify(clone.variables, null, 2)); // Save Stage & Region Variables @@ -177,12 +177,12 @@ class ServerlessMeta let stage = clone.stages[Object.keys(clone.stages)[i]]; // Save Stage Variables - fs.writeFileSync(this._S.getProject().getFilePath('_meta', 'variables', 's-variables-' + Object.keys(clone.stages)[i] + '.json'), + fs.writeFileSync(_this._S.getProject().getFilePath('_meta', 'variables', 's-variables-' + Object.keys(clone.stages)[i] + '.json'), JSON.stringify(stage.variables, null, 2)); // Save Stage Region Variables for (let j = 0; j < Object.keys(stage.regions).length; j++) { - fs.writeFileSync(this._S.getProject().getFilePath('_meta', 'variables', 's-variables-' + Object.keys(clone.stages)[i] + '-' + Object.keys(stage.regions)[j].replace(/-/g, '') + '.json'), + fs.writeFileSync(_this._S.getProject().getFilePath('_meta', 'variables', 's-variables-' + Object.keys(clone.stages)[i] + '-' + Object.keys(stage.regions)[j].replace(/-/g, '') + '.json'), JSON.stringify(stage.regions[Object.keys(stage.regions)[j]].variables, null, 2)); } } diff --git a/lib/ServerlessProject.js b/lib/ServerlessProject.js index be9682d9d..55a396ea6 100644 --- a/lib/ServerlessProject.js +++ b/lib/ServerlessProject.js @@ -36,8 +36,6 @@ class ServerlessProject { _this.components = {}; _this.templates = {}; _this.plugins = []; - - _this.load(); } //TODO: get rid of this? @@ -60,11 +58,13 @@ class ServerlessProject { let projectJson = require(path.join(fullPath, jsonName)); if (typeof projectJson.name !== 'undefined') { project = new ServerlessProject( fullPath ); + project.load(); break; } } previous = path.join(previous, '..'); + i--; } return project; diff --git a/lib/actions/EnvSet.js b/lib/actions/EnvSet.js index 1e7408b00..989770de7 100644 --- a/lib/actions/EnvSet.js +++ b/lib/actions/EnvSet.js @@ -168,7 +168,7 @@ usage: serverless env set`, _setEnvVar(){ let _this = this; - return awsMisc.getEnvFiles(this.S, _this.evt.options.region, _this.evt.options.stage) + return awsMisc.getEnvFiles(_this.S, _this.evt.options.region, _this.evt.options.stage) .then(envMapsByRegion => { let putEnvQ = []; @@ -185,7 +185,7 @@ usage: serverless env set`, }); if (_this.evt.options.stage == 'local') { - putEnvQ.push(SUtils.writeFile(this.S.getProject().getFilePath('.env'), contents)); + putEnvQ.push(SUtils.writeFile(_this.S.getProject().getFilePath('.env'), contents)); } else { let projectName = _this.S.state.meta.get().variables.project, bucketName = _this.S.state.meta.get().variables.projectBucket, diff --git a/lib/actions/FunctionCreate.js b/lib/actions/FunctionCreate.js index 2cb711ddf..830a6b704 100644 --- a/lib/actions/FunctionCreate.js +++ b/lib/actions/FunctionCreate.js @@ -163,11 +163,11 @@ usage: serverless function create `, let dir = _this.evt.options.sPath.split('/'); dir.pop(); let c = dir.shift(); - if (dir[0] && !SUtils.dirExistsSync(_this.S.project.getFilePath(c, dir[0]))) { - fs.mkdirSync(_this.S.project.getFilePath(c, dir[0])); + if (dir[0] && !SUtils.dirExistsSync(_this.S.getProject().getFilePath(c, dir[0]))) { + fs.mkdirSync(_this.S.getProject().getFilePath(c, dir[0])); } - if (dir[1] && !SUtils.dirExistsSync(_this.S.project.getFilePath(c, dir[0], dir[1]))) { - fs.mkdirSync(_this.S.project.getFilePath(c, dir[0], dir[1])); + if (dir[1] && !SUtils.dirExistsSync(_this.S.getProject().getFilePath(c, dir[0], dir[1]))) { + fs.mkdirSync(_this.S.getProject().getFilePath(c, dir[0], dir[1])); } } diff --git a/lib/actions/FunctionDeploy.js b/lib/actions/FunctionDeploy.js index 459cb67d8..19d164e1d 100644 --- a/lib/actions/FunctionDeploy.js +++ b/lib/actions/FunctionDeploy.js @@ -211,8 +211,8 @@ module.exports = function(SPlugin, serverlessPath) { } // Ensure tmp folder exists in _meta - if (!SUtils.dirExistsSync(_this.S.project.getFilePath('_meta', '_tmp'))) { - fs.mkdirSync(_this.S.project.getFilePath('_meta', '_tmp')); + if (!SUtils.dirExistsSync(_this.S.getProject().getFilePath('_meta', '_tmp'))) { + fs.mkdirSync(_this.S.getProject().getFilePath('_meta', '_tmp')); } return BbPromise.resolve(); diff --git a/lib/actions/ModuleInstall.js b/lib/actions/ModuleInstall.js index 49a7495ed..6b491d867 100644 --- a/lib/actions/ModuleInstall.js +++ b/lib/actions/ModuleInstall.js @@ -173,7 +173,7 @@ usage: serverless module install `, } _this.evt.data.module = srcModuleJson.name; - _this.pathModule = _this.S.project.getFilePath('back', 'modules', _this.evt.data.module); + _this.pathModule = _this.S.getProject().getFilePath('back', 'modules', _this.evt.data.module); // if same module name exists, throw error if (SUtils.doesModuleExist(srcModuleJson.name, this.S.getProject().getRootPath())) { diff --git a/lib/actions/ProjectInit.js b/lib/actions/ProjectInit.js index 372ba28bf..7173c36d5 100644 --- a/lib/actions/ProjectInit.js +++ b/lib/actions/ProjectInit.js @@ -364,7 +364,7 @@ module.exports = function(SPlugin, serverlessPath) { // Create s-resources-cf.json if (!_this.project.cloudFormation && // In case initializing older project w/ cloudFormation property - !SUtils.fileExistsSync( _.this.project.getFilePath( 's-resources-cf.json' ))) { + !SUtils.fileExistsSync( _this.project.getFilePath( 's-resources-cf.json' ))) { files.push( SUtils.writeFile( _this.project.getFilePath( 's-resources-cf.json' ), @@ -377,6 +377,7 @@ module.exports = function(SPlugin, serverlessPath) { // Save State return _this.S.state.save() .then(function() { + _this.S.getProject().load(); return _this.S.state.load(); }); }) diff --git a/lib/actions/ProjectInstall.js b/lib/actions/ProjectInstall.js index 06ef686a0..b2641fe66 100644 --- a/lib/actions/ProjectInstall.js +++ b/lib/actions/ProjectInstall.js @@ -210,7 +210,9 @@ module.exports = function(SPlugin, serverlessPath) { // Update Global Serverless Instance if( !_this.S.hasProject() ) { let projectPath = path.resolve(path.join(path.dirname('.'), _this.evt.options.name ? _this.evt.options.name : _this.evt.options.project)); - _this.S.setProject( new _this.S.classes.Project( projectPath ) ); + let project = new _this.S.classes.Project( projectPath ); + project.load(); + _this.S.setProject( project ); } // Load state again now that the project is set diff --git a/lib/actions/RegionRemove.js b/lib/actions/RegionRemove.js index 1daeea3c7..ea5ad064b 100644 --- a/lib/actions/RegionRemove.js +++ b/lib/actions/RegionRemove.js @@ -197,7 +197,7 @@ usage: serverless region remove`, _removeVariables() { let fileName = `s-variables-${this.evt.options.stage}-${this.evt.options.region.replace(/-/g, '')}.json`; - return fs.unlinkAsync(this.S.project.getFilePath('_meta', 'variables', fileName)); + return fs.unlinkAsync(this.S.getProject().getFilePath('_meta', 'variables', fileName)); } diff --git a/lib/actions/ResourcesDeploy.js b/lib/actions/ResourcesDeploy.js index f902be5e1..e0af016ae 100644 --- a/lib/actions/ResourcesDeploy.js +++ b/lib/actions/ResourcesDeploy.js @@ -167,7 +167,7 @@ usage: serverless resources deploy`, console.log(resources); // Create CloudFormation template in _meta folder return SUtils.writeFile( - _this.S.project.getFilePath('_meta', 'resources', 's-resources-cf-' + _this.evt.options.stage + '-' + replaceall('-', '', _this.evt.options.region) + '.json'), + _this.S.getProject().getFilePath('_meta', 'resources', 's-resources-cf-' + _this.evt.options.stage + '-' + replaceall('-', '', _this.evt.options.region) + '.json'), JSON.stringify(_this.cfTemplate, null, 2)) }) diff --git a/lib/actions/ResourcesRemove.js b/lib/actions/ResourcesRemove.js index 1610483d7..7c98ce01a 100644 --- a/lib/actions/ResourcesRemove.js +++ b/lib/actions/ResourcesRemove.js @@ -183,7 +183,7 @@ usage: serverless resources remove`, let removeLocalResourceFile = function() { let fileName = `s-resources-cf-${stage}-${region.replace(/-/g, '')}.json`; - let resourcesLocalFilePath = _this.S.project.getFilePath('_meta', 'resources', fileName); + let resourcesLocalFilePath = _this.S.getProject().getFilePath('_meta', 'resources', fileName); if (SUtils.fileExistsSync(resourcesLocalFilePath)) { SUtils.sDebug(`Removing resources file "${fileName}"`); diff --git a/lib/actions/StageRemove.js b/lib/actions/StageRemove.js index 72031bc91..10a12b91e 100644 --- a/lib/actions/StageRemove.js +++ b/lib/actions/StageRemove.js @@ -123,7 +123,7 @@ usage: serverless stage remove`, _removeVariables() { let fileName = `s-variables-${this.evt.options.stage}.json`; - return fs.unlinkAsync(this.S.project.getFilePath('_meta', 'variables', fileName)); + return fs.unlinkAsync(this.S.getProject().getFilePath('_meta', 'variables', fileName)); } _removeMeta() { From 34f30d9e66e18ba77dbc0177d2f8f9cfe0ba3cd3 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Tue, 9 Feb 2016 17:55:00 +0100 Subject: [PATCH 06/17] Cleanups --- lib/ServerlessState.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ServerlessState.js b/lib/ServerlessState.js index e0ed203f1..746d42738 100644 --- a/lib/ServerlessState.js +++ b/lib/ServerlessState.js @@ -60,7 +60,6 @@ class ServerlessState { set(data) { this.meta = data.meta ? this.meta.set(data.meta) : this.meta; - this.project = data.project ? this._S.getProject().set(data.project, { deep: true }) : this._S.getProject(); return this; } From c5e644626a4e87f91f70e7010e52ea237fd4830d Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Tue, 9 Feb 2016 18:19:59 +0100 Subject: [PATCH 07/17] Updates for testsuite --- lib/ServerlessState.js | 1 + tests/tests/classes/ServerlessStateTest.js | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/ServerlessState.js b/lib/ServerlessState.js index 746d42738..e0ed203f1 100644 --- a/lib/ServerlessState.js +++ b/lib/ServerlessState.js @@ -60,6 +60,7 @@ class ServerlessState { set(data) { this.meta = data.meta ? this.meta.set(data.meta) : this.meta; + this.project = data.project ? this._S.getProject().set(data.project, { deep: true }) : this._S.getProject(); return this; } diff --git a/tests/tests/classes/ServerlessStateTest.js b/tests/tests/classes/ServerlessStateTest.js index d77e656cd..0059f657b 100644 --- a/tests/tests/classes/ServerlessStateTest.js +++ b/tests/tests/classes/ServerlessStateTest.js @@ -5,6 +5,7 @@ */ let Serverless = require('../../../lib/Serverless.js'), + Project = require('../../../lib/ServerlessProject'), path = require('path'), utils = require('../../../lib/utils/index'), assert = require('chai').assert, @@ -24,9 +25,10 @@ describe('Test Serverless State Class', function() { process.chdir(projPath); // Instantiate Serverless - serverless = new Serverless({ - interactive: false, - projectPath: projPath + let project = new Project( projPath ); + project.load(); + serverless = new Serverless( project, { + interactive: false }); return serverless.init() @@ -73,7 +75,7 @@ describe('Test Serverless State Class', function() { let clone = instance.get(); clone.project.name = 'newProject'; instance.set(clone); - assert.equal(true, instance.project.name === 'newProject'); + assert.equal(true, instance._S.getProject().name === 'newProject'); done(); }); @@ -225,9 +227,10 @@ describe('Test Serverless State Class', function() { it('Set Assets', function(done) { - let project = new instance._S.classes.Project(instance._S); - project.name = 'testProject'; - instance.setAsset(project); + //TODO + //let project = new instance._S.classes.Project("."); + //project.name = 'testProject'; + //instance.setAsset(project); let component = new instance._S.classes.Component(instance._S, { sPath: 'testComponent' }); component.name = 'testComponent'; @@ -241,7 +244,8 @@ describe('Test Serverless State Class', function() { endpoint.path = 'test/endpoint'; instance.setAsset(endpoint); - assert.equal(true, instance.project.name === 'testProject'); + // TODO + //assert.equal(true, instance._S.getProject().name === 'testProject'); assert.equal(true, typeof instance.project.components[component.name] !== 'undefined'); assert.equal(true, typeof instance.project.components[component.name].functions[func._config.sPath] !== 'undefined'); assert.equal(true, instance.project.components[component.name].functions[func._config.sPath].endpoints.length > 0); From 6c80533d27c59b06e79cf356c4b0f82d788ae8dd Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Wed, 10 Feb 2016 08:56:21 +0100 Subject: [PATCH 08/17] Update ServerlessEvent for the recent interface changes --- lib/ServerlessEvent.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/ServerlessEvent.js b/lib/ServerlessEvent.js index 692f31610..28a36116a 100644 --- a/lib/ServerlessEvent.js +++ b/lib/ServerlessEvent.js @@ -53,9 +53,8 @@ class ServerlessEvent { } // Make full path - if (this._S.config.projectPath && this._config.sPath) { - this._config.fullPath = path.join( - this._S.config.projectPath, + if (this._S.hasProject() && this._config.sPath) { + this._config.fullPath = this._S.getProject().getFilePath( this._config.sPath.split('#')[0].split('/').join(path.sep) ); } @@ -74,7 +73,7 @@ class ServerlessEvent { return new BbPromise(function(resolve) { // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Event could not be loaded because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Event could not be loaded because no project has been set on Serverless instance'); // Validate: Check function exists if (!SUtils.fileExistsSync(path.join(_this._config.fullPath, 's-function.json'))) { @@ -136,8 +135,8 @@ class ServerlessEvent { // Validate: Check Stage & Region if (!options.stage || !options.region) throw new SError('Both "stage" and "region" params are required'); - // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Event could not be populated because no project path has been set on Serverless instance'); + // Validate: Check project is set + if (!_this._S.hasProject()) throw new SError('Event could not be populated because no project has been set on Serverless instance'); // Populate let clone = _this.get(); @@ -172,7 +171,7 @@ class ServerlessEvent { return new BbPromise(function(resolve) { // Validate: Check project path is set - if (!_this._S.config.projectPath) throw new SError('Event could not be saved because no project path has been set on Serverless instance'); + if (!_this._S.hasProject()) throw new SError('Event could not be saved because no project has been set on Serverless instance'); // Validate: Check function exists if (!SUtils.fileExistsSync(path.join(_this._config.fullPath, 's-function.json'))) { From 4a358cc9ad83dc8e079c88e39898262e048ff3a5 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Wed, 10 Feb 2016 09:06:24 +0100 Subject: [PATCH 09/17] Update event actions for the recent interface changes --- lib/actions/EventDeploy.js | 4 ++-- lib/actions/EventDeployS3Lambda.js | 2 +- lib/actions/EventDeploySNSLambda.js | 2 +- lib/actions/EventDeployScheduledLambda.js | 2 +- lib/actions/EventDeployStreamLambda.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/actions/EventDeploy.js b/lib/actions/EventDeploy.js index 847b45bdd..e083f66fb 100644 --- a/lib/actions/EventDeploy.js +++ b/lib/actions/EventDeploy.js @@ -144,7 +144,7 @@ module.exports = function(SPlugin, serverlessPath) { let _this = this; // Instantiate Classes - _this.project = _this.S.state.getProject(); + _this.project = _this.S.getProject(); _this.meta = _this.S.state.getMeta(); // Set defaults @@ -157,7 +157,7 @@ module.exports = function(SPlugin, serverlessPath) { !_this.evt.options.all) { // Get all functions in CWD - let sPath = _this.getSPathFromCwd(_this.S.config.projectPath); + let sPath = _this.getSPathFromCwd(_this.S.getProject().getRootPath()); if (!sPath) { throw new SError(`You must be in a component to deploy events`); diff --git a/lib/actions/EventDeployS3Lambda.js b/lib/actions/EventDeployS3Lambda.js index d5d1d2262..3658bc67d 100644 --- a/lib/actions/EventDeployS3Lambda.js +++ b/lib/actions/EventDeployS3Lambda.js @@ -52,7 +52,7 @@ module.exports = function(SPlugin, serverlessPath) { let event = _this.S.state.getEvents({ paths: [_this.evt.options.path] })[0], populatedEvent = event.getPopulated({stage: _this.evt.options.stage, region: _this.evt.options.region}), awsAccountId = _this.S.state.meta.get().stages[_this.evt.options.stage].regions[_this.evt.options.region].variables.iamRoleArnLambda.split('::')[1].split(':')[0], - lambdaArn = "arn:aws:lambda:" + _this.evt.options.region + ":" + awsAccountId + ":function:" + _this.S.state.getProject().name + "-" + _this.evt.options.path.split('/')[0] + "-" + _this.evt.options.path.split('/')[1] + "-" + _this.evt.options.path.split('/')[2].split('#')[0]; + lambdaArn = "arn:aws:lambda:" + _this.evt.options.region + ":" + awsAccountId + ":function:" + _this.S.getProject().getName() + "-" + _this.evt.options.path.split('/')[0] + "-" + _this.evt.options.path.split('/')[1] + "-" + _this.evt.options.path.split('/')[2].split('#')[0]; let awsConfig = { region: _this.evt.options.region, diff --git a/lib/actions/EventDeploySNSLambda.js b/lib/actions/EventDeploySNSLambda.js index 4dc8bc5c4..ac4ef30fe 100644 --- a/lib/actions/EventDeploySNSLambda.js +++ b/lib/actions/EventDeploySNSLambda.js @@ -53,7 +53,7 @@ module.exports = function(SPlugin, serverlessPath) { let event = _this.S.state.getEvents({ paths: [_this.evt.options.path] })[0], populatedEvent = event.getPopulated({stage: _this.evt.options.stage, region: _this.evt.options.region}), awsAccountId = _this.S.state.meta.get().stages[_this.evt.options.stage].regions[_this.evt.options.region].variables.iamRoleArnLambda.split('::')[1].split(':')[0], - lambdaArn = "arn:aws:lambda:" + _this.evt.options.region + ":" + awsAccountId + ":function:" + _this.S.state.getProject().name + "-" + _this.evt.options.path.split('/')[0] + "-" + _this.evt.options.path.split('/')[1] + "-" + _this.evt.options.path.split('/')[2].split('#')[0] + ":" + _this.evt.options.stage; + lambdaArn = "arn:aws:lambda:" + _this.evt.options.region + ":" + awsAccountId + ":function:" + _this.S.getProject().getName() + "-" + _this.evt.options.path.split('/')[0] + "-" + _this.evt.options.path.split('/')[1] + "-" + _this.evt.options.path.split('/')[2].split('#')[0] + ":" + _this.evt.options.stage; let awsConfig = { region: _this.evt.options.region, diff --git a/lib/actions/EventDeployScheduledLambda.js b/lib/actions/EventDeployScheduledLambda.js index d2c82e31e..0b6887c51 100644 --- a/lib/actions/EventDeployScheduledLambda.js +++ b/lib/actions/EventDeployScheduledLambda.js @@ -53,7 +53,7 @@ module.exports = function (SPlugin, serverlessPath) { populatedEvent = event.getPopulated({stage: _this.evt.options.stage, region: _this.evt.options.region}), pathName = _this.evt.options.path.replace(/\//g, '-').replace('#', '-'), awsAccountId = _this.S.state.meta.get().stages[_this.evt.options.stage].regions[_this.evt.options.region].variables.iamRoleArnLambda.split('::')[1].split(':')[0], - lambdaArn = "arn:aws:lambda:" + _this.evt.options.region + ":" + awsAccountId + ":function:" + _this.S.state.getProject().name + "-" + _this.evt.options.path.split('/')[0] + "-" + _this.evt.options.path.split('/')[1] + "-" + _this.evt.options.path.split('/')[2].split('#')[0] + ":" + _this.evt.options.stage; + lambdaArn = "arn:aws:lambda:" + _this.evt.options.region + ":" + awsAccountId + ":function:" + _this.S.getProject().getName() + "-" + _this.evt.options.path.split('/')[0] + "-" + _this.evt.options.path.split('/')[1] + "-" + _this.evt.options.path.split('/')[2].split('#')[0] + ":" + _this.evt.options.stage; populatedEvent.config.enabled = populatedEvent.config.enabled ? 'ENABLED' : 'DISABLED'; diff --git a/lib/actions/EventDeployStreamLambda.js b/lib/actions/EventDeployStreamLambda.js index 0173af50f..642c1bf77 100644 --- a/lib/actions/EventDeployStreamLambda.js +++ b/lib/actions/EventDeployStreamLambda.js @@ -64,7 +64,7 @@ module.exports = function(SPlugin, serverlessPath) { regionVars = _this.S.state.getMeta().stages[_this.evt.options.stage].regions[_this.evt.options.region].variables, eventVar = 'eventID:' + event._config.sPath, awsAccountId = _this.S.state.meta.get().stages[_this.evt.options.stage].regions[_this.evt.options.region].variables.iamRoleArnLambda.split('::')[1].split(':')[0], - lambdaArn = "arn:aws:lambda:" + _this.evt.options.region + ":" + awsAccountId + ":function:" + _this.S.state.getProject().name + "-" + _this.evt.options.path.split('/')[0] + "-" + _this.evt.options.path.split('/')[1] + "-" + _this.evt.options.path.split('/')[2].split('#')[0] + ":" + _this.evt.options.stage; + lambdaArn = "arn:aws:lambda:" + _this.evt.options.region + ":" + awsAccountId + ":function:" + _this.S.getProject().getName() + "-" + _this.evt.options.path.split('/')[0] + "-" + _this.evt.options.path.split('/')[1] + "-" + _this.evt.options.path.split('/')[2].split('#')[0] + ":" + _this.evt.options.stage; populatedEvent.config.startingPosition = populatedEvent.config.startingPosition || 'TRIM_HORIZON'; populatedEvent.config.batchSize = populatedEvent.config.batchSize || 100; From 8a072fd7cd861133d9601d53940decb01036b752 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Wed, 10 Feb 2016 09:08:23 +0100 Subject: [PATCH 10/17] Added support for passing only path to project to Serverless constructor, so programmatic use can be sometimes more convenient. --- lib/Serverless.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/Serverless.js b/lib/Serverless.js index 6cf2093d1..8311afbae 100644 --- a/lib/Serverless.js +++ b/lib/Serverless.js @@ -88,6 +88,10 @@ class Serverless { } setProject( project ) { + if( _.isString( project ) ){ + project = this.classes.Project.findProject( project ); + } + this._project = project; if( project != undefined ){ From e570f077e2f312d9ef644c77fc91ef2cc7e5df9c Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Wed, 10 Feb 2016 09:18:28 +0100 Subject: [PATCH 11/17] Serverless classes are now loaded before setProject() call --- lib/Serverless.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/Serverless.js b/lib/Serverless.js index 8311afbae..e1fafef41 100644 --- a/lib/Serverless.js +++ b/lib/Serverless.js @@ -39,16 +39,7 @@ class Serverless { serverlessPath: __dirname }; - this.setProject( project ); - - // Add Config Settings - this.updateConfig(config); - - // Add Defaults - this.actions = {}; - this.hooks = {}; - this.commands = {}; - this.classes = { + this.classes = { // TODO: add Runtime, Stage, Region State: require('./ServerlessState'), Meta: require('./ServerlessMeta'), @@ -58,6 +49,16 @@ class Serverless { Endpoint: require('./ServerlessEndpoint'), Event: require('./ServerlessEvent') }; + + this.setProject( project ); + + // Add Config Settings + this.updateConfig(config); + + // Add Defaults + this.actions = {}; + this.hooks = {}; + this.commands = {}; this.cli = null; this.state = new this.classes.State(this); From 9064a77148774533a6b259890ae05285319d60c7 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Wed, 10 Feb 2016 09:23:37 +0100 Subject: [PATCH 12/17] Updated unnecessary getProject() with hasProject() --- lib/actions/ProjectInit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/actions/ProjectInit.js b/lib/actions/ProjectInit.js index 7173c36d5..260594939 100644 --- a/lib/actions/ProjectInit.js +++ b/lib/actions/ProjectInit.js @@ -145,7 +145,7 @@ module.exports = function(SPlugin, serverlessPath) { if (_this.evt.options.name) isName = true; // Check if project exists - if (_this.S.getProject()) { + if (_this.S.hasProject()) { // Set temp name name = _this.evt.options.name ? _this.evt.options.name : (_this.S.getProject().getName() + '-' + SUtils.generateShortId(6)).toLowerCase(); } else { From 27a7acf8777ad89f80cf4d9b88bc2d59a6ea3c3b Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Wed, 10 Feb 2016 10:36:39 +0100 Subject: [PATCH 13/17] Updated tests to match recent architectural changes --- tests/tests/actions/ComponentCreate.js | 5 ++--- tests/tests/actions/EndpointDeploy.js | 5 ++--- tests/tests/actions/EnvGet.js | 5 ++--- tests/tests/actions/EnvList.js | 5 ++--- tests/tests/actions/EnvSetUnset.js | 5 ++--- tests/tests/actions/EventDeploy.js | 5 ++--- tests/tests/actions/FunctionCreate.js | 7 +++---- tests/tests/actions/FunctionDeploy.js | 5 ++--- tests/tests/actions/FunctionLogs.js | 5 ++--- tests/tests/actions/FunctionRun.js | 5 ++--- tests/tests/actions/ModuleCreate.js | 7 +++---- tests/tests/actions/ProjectInit.js | 2 +- tests/tests/actions/ProjectInstall.js | 2 +- tests/tests/actions/RegionCreate.js | 5 ++--- tests/tests/actions/ResourcesDeploy.js | 7 +++---- tests/tests/actions/StageCreate.js | 5 ++--- tests/tests/actions/TestDefaultActionHook.js | 5 ++--- tests/tests/actions/TestPluginCustom.js | 2 +- tests/tests/actions/projectLifeCycle.js | 2 +- tests/tests/classes/ServerlessComponentTest.js | 5 ++--- tests/tests/classes/ServerlessEndpointTest.js | 5 ++--- tests/tests/classes/ServerlessFunctionTest.js | 5 ++--- tests/tests/classes/ServerlessProjectTest.js | 15 ++++++++++----- tests/tests/classes/ServerlessStateTest.js | 4 +--- 24 files changed, 54 insertions(+), 69 deletions(-) diff --git a/tests/tests/actions/ComponentCreate.js b/tests/tests/actions/ComponentCreate.js index 559f48161..9bd97682d 100644 --- a/tests/tests/actions/ComponentCreate.js +++ b/tests/tests/actions/ComponentCreate.js @@ -34,9 +34,8 @@ describe('Test action: Component Create', function() { process.chdir(projPath); - serverless = new Serverless({ - interactive: false, - projectPath: projPath + serverless = new Serverless( projPath, { + interactive: false }); return serverless.state.load().then(function() { diff --git a/tests/tests/actions/EndpointDeploy.js b/tests/tests/actions/EndpointDeploy.js index db2a10712..ff363fb7e 100644 --- a/tests/tests/actions/EndpointDeploy.js +++ b/tests/tests/actions/EndpointDeploy.js @@ -48,11 +48,10 @@ describe('Test Action: Endpoint Deploy', function() { process.chdir(projPath); - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.state.load().then(function() { diff --git a/tests/tests/actions/EnvGet.js b/tests/tests/actions/EnvGet.js index 0b29881e8..9911e3ce4 100644 --- a/tests/tests/actions/EnvGet.js +++ b/tests/tests/actions/EnvGet.js @@ -36,11 +36,10 @@ describe('Test Action: Env Get', function() { process.chdir(projPath); - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.state.load().then(function() { diff --git a/tests/tests/actions/EnvList.js b/tests/tests/actions/EnvList.js index 9fbc10796..3ab2fe3ab 100644 --- a/tests/tests/actions/EnvList.js +++ b/tests/tests/actions/EnvList.js @@ -38,11 +38,10 @@ describe('Test Action: Env List', function() { process.chdir(projPath); - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.state.load().then(function() { diff --git a/tests/tests/actions/EnvSetUnset.js b/tests/tests/actions/EnvSetUnset.js index 0cf55eb7b..5ca7e0c0e 100644 --- a/tests/tests/actions/EnvSetUnset.js +++ b/tests/tests/actions/EnvSetUnset.js @@ -40,11 +40,10 @@ describe('Test Env Set & Env Unset actions', function() { process.chdir(projPath); - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.state.load().then(function() { diff --git a/tests/tests/actions/EventDeploy.js b/tests/tests/actions/EventDeploy.js index d2fc81723..083545b11 100644 --- a/tests/tests/actions/EventDeploy.js +++ b/tests/tests/actions/EventDeploy.js @@ -48,11 +48,10 @@ describe('Test Action: Event Deploy', function() { process.chdir(projPath); - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.state.load().then(function() { diff --git a/tests/tests/actions/FunctionCreate.js b/tests/tests/actions/FunctionCreate.js index 6a4d57fb8..c7aff9062 100644 --- a/tests/tests/actions/FunctionCreate.js +++ b/tests/tests/actions/FunctionCreate.js @@ -35,9 +35,8 @@ describe('Test action: Function Create', function() { process.chdir(projPath); - serverless = new Serverless({ - interactive: false, - projectPath: projPath + serverless = new Serverless( projPath, { + interactive: false }); return serverless.state.load().then(function() { @@ -64,7 +63,7 @@ describe('Test action: Function Create', function() { serverless.actions.functionCreate(evt) .then(function(evt) { validateEvent(evt); - let functionJson = utils.readAndParseJsonSync(path.join(serverless.config.projectPath, 'nodejscomponent', 'group1', 'function1', 's-function.json')); + let functionJson = utils.readAndParseJsonSync(serverless.getProject().getFilePath( 'nodejscomponent', 'group1', 'function1', 's-function.json')); assert.equal(true, typeof functionJson.name != 'undefined'); assert.equal(true, functionJson.endpoints.length); done(); diff --git a/tests/tests/actions/FunctionDeploy.js b/tests/tests/actions/FunctionDeploy.js index 1cecc1fa2..51aa7125f 100644 --- a/tests/tests/actions/FunctionDeploy.js +++ b/tests/tests/actions/FunctionDeploy.js @@ -76,11 +76,10 @@ describe('Test Action: Function Deploy', function() { process.chdir(projPath); - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.state.load().then(function() { diff --git a/tests/tests/actions/FunctionLogs.js b/tests/tests/actions/FunctionLogs.js index 7b382bd8e..80f75963a 100644 --- a/tests/tests/actions/FunctionLogs.js +++ b/tests/tests/actions/FunctionLogs.js @@ -41,11 +41,10 @@ describe('Test action: Function Logs', function() { .then(projPath => { process.chdir(projPath); - serverless = new Serverless({ + serverless = new Serverless( projPath, { awsAdminKeyId: config.awsAdminKeyId, awsAdminSecretKey: config.awsAdminSecretKey, - interactive: false, - projectPath: projPath + interactive: false }); return serverless.state.load(); }) diff --git a/tests/tests/actions/FunctionRun.js b/tests/tests/actions/FunctionRun.js index b12eee3d3..e2f96d14b 100644 --- a/tests/tests/actions/FunctionRun.js +++ b/tests/tests/actions/FunctionRun.js @@ -36,11 +36,10 @@ describe('Test Action: Function Run', function() { process.chdir(projPath); - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: true, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.state.load() diff --git a/tests/tests/actions/ModuleCreate.js b/tests/tests/actions/ModuleCreate.js index 9d6c0a06e..f0e88043d 100644 --- a/tests/tests/actions/ModuleCreate.js +++ b/tests/tests/actions/ModuleCreate.js @@ -36,9 +36,8 @@ describe('Test action: Module Create', function() { process.chdir(projPath); - serverless = new Serverless({ - interactive: false, - projectPath: projPath + serverless = new Serverless( projPath, { + interactive: false }); return serverless.state.load().then(function() { @@ -67,7 +66,7 @@ describe('Test action: Module Create', function() { serverless.actions.moduleCreate(evt) .then(function(evt) { - let functionJson = utils.readAndParseJsonSync(path.join(serverless.config.projectPath, 'nodejscomponent', 'newmodule', 'newfunction', 's-function.json')); + let functionJson = utils.readAndParseJsonSync(serverless.getProject().getFilePath( 'nodejscomponent', 'newmodule', 'newfunction', 's-function.json')); assert.equal(true, typeof functionJson.name != 'undefined'); assert.equal(true, functionJson.endpoints.length); diff --git a/tests/tests/actions/ProjectInit.js b/tests/tests/actions/ProjectInit.js index 4143ab789..1106a3bee 100644 --- a/tests/tests/actions/ProjectInit.js +++ b/tests/tests/actions/ProjectInit.js @@ -18,7 +18,7 @@ let Serverless = require('../../../lib/Serverless'), config = require('../../config'); // Instantiate -let serverless = new Serverless({ +let serverless = new Serverless( undefined, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, awsAdminSecretKey: config.awsAdminSecretKey diff --git a/tests/tests/actions/ProjectInstall.js b/tests/tests/actions/ProjectInstall.js index b553a942e..ac16952c5 100644 --- a/tests/tests/actions/ProjectInstall.js +++ b/tests/tests/actions/ProjectInstall.js @@ -18,7 +18,7 @@ let Serverless = require('../../../lib/Serverless'), config = require('../../config'); // Instantiate -let serverless = new Serverless({ +let serverless = new Serverless( undefined, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, awsAdminSecretKey: config.awsAdminSecretKey diff --git a/tests/tests/actions/RegionCreate.js b/tests/tests/actions/RegionCreate.js index eb768b627..a9d9c1e50 100644 --- a/tests/tests/actions/RegionCreate.js +++ b/tests/tests/actions/RegionCreate.js @@ -71,11 +71,10 @@ describe('Test Action: Region Create', function() { this.timeout(0); process.chdir(projPath); // Ror some weird reason process.chdir adds /private/ before cwd path - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.state.load().then(function() { diff --git a/tests/tests/actions/ResourcesDeploy.js b/tests/tests/actions/ResourcesDeploy.js index 4afa8452d..393f5929b 100644 --- a/tests/tests/actions/ResourcesDeploy.js +++ b/tests/tests/actions/ResourcesDeploy.js @@ -39,11 +39,10 @@ describe('Test action: Resources Deploy', function() { process.chdir(projPath); - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.init() @@ -51,7 +50,7 @@ describe('Test action: Resources Deploy', function() { SUtils.sDebug('Adding test bucket resource'); - let newProject = serverless.project.get(); + let newProject = serverless.getProject().get(); // Adding new Module resource newProject.cloudFormation.Resources['testBucket' + (new Date).getTime().toString()] = { "Type" : "AWS::S3::Bucket" }; diff --git a/tests/tests/actions/StageCreate.js b/tests/tests/actions/StageCreate.js index eecb7f590..7f59ea81c 100644 --- a/tests/tests/actions/StageCreate.js +++ b/tests/tests/actions/StageCreate.js @@ -68,11 +68,10 @@ describe('Test Action: Stage Create', function() { this.timeout(0); process.chdir(projPath); - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.state.load().then(function() { diff --git a/tests/tests/actions/TestDefaultActionHook.js b/tests/tests/actions/TestDefaultActionHook.js index cb0727c93..44643db90 100644 --- a/tests/tests/actions/TestDefaultActionHook.js +++ b/tests/tests/actions/TestDefaultActionHook.js @@ -81,9 +81,8 @@ describe('Test Default Action With Pre Hook', function() { .then(projPath => { process.chdir(projPath); - serverless = new Serverless({ - interactive: false, - projectPath: projPath + serverless = new Serverless( projPath, { + interactive: false }); serverless.addPlugin(new CustomPlugin(serverless, {})); diff --git a/tests/tests/actions/TestPluginCustom.js b/tests/tests/actions/TestPluginCustom.js index 4fff0b84d..a8eda16f4 100644 --- a/tests/tests/actions/TestPluginCustom.js +++ b/tests/tests/actions/TestPluginCustom.js @@ -251,7 +251,7 @@ describe('Test Custom Plugin', function() { before(function(done) { - serverless = new Serverless({ + serverless = new Serverless( undefined, { awsAdminKeyId: '123', awsAdminSecretKey: '123', interactive: false diff --git a/tests/tests/actions/projectLifeCycle.js b/tests/tests/actions/projectLifeCycle.js index 217d76736..4618547ea 100644 --- a/tests/tests/actions/projectLifeCycle.js +++ b/tests/tests/actions/projectLifeCycle.js @@ -26,7 +26,7 @@ let Serverless = require('../../../lib/Serverless'), config = require('../../config'); -let serverless = new Serverless({ +let serverless = new Serverless( undefined, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, awsAdminSecretKey: config.awsAdminSecretKey diff --git a/tests/tests/classes/ServerlessComponentTest.js b/tests/tests/classes/ServerlessComponentTest.js index 310dfba31..12fc9d937 100644 --- a/tests/tests/classes/ServerlessComponentTest.js +++ b/tests/tests/classes/ServerlessComponentTest.js @@ -25,9 +25,8 @@ describe('Test Serverless Component Class', function() { process.chdir(projPath); // Instantiate Serverless - serverless = new Serverless({ - interactive: false, - projectPath: projPath + serverless = new Serverless( projPath, { + interactive: false }); return serverless.init() diff --git a/tests/tests/classes/ServerlessEndpointTest.js b/tests/tests/classes/ServerlessEndpointTest.js index a1f3e0052..4f3f292eb 100644 --- a/tests/tests/classes/ServerlessEndpointTest.js +++ b/tests/tests/classes/ServerlessEndpointTest.js @@ -24,9 +24,8 @@ describe('Test Serverless Endpoint Class', function() { process.chdir(projPath); // Instantiate Serverless - serverless = new Serverless({ - interactive: false, - projectPath: projPath + serverless = new Serverless( projPath, { + interactive: false }); return serverless.init() diff --git a/tests/tests/classes/ServerlessFunctionTest.js b/tests/tests/classes/ServerlessFunctionTest.js index fd047ff8d..681d33754 100644 --- a/tests/tests/classes/ServerlessFunctionTest.js +++ b/tests/tests/classes/ServerlessFunctionTest.js @@ -24,9 +24,8 @@ describe('Test Serverless Function Class', function() { process.chdir(projPath); // Instantiate Serverless - serverless = new Serverless({ - interactive: false, - projectPath: projPath + serverless = new Serverless( projPath, { + interactive: false }); return serverless.init() diff --git a/tests/tests/classes/ServerlessProjectTest.js b/tests/tests/classes/ServerlessProjectTest.js index 6e34c5d11..59d8234ac 100644 --- a/tests/tests/classes/ServerlessProjectTest.js +++ b/tests/tests/classes/ServerlessProjectTest.js @@ -25,16 +25,15 @@ describe('Test Serverless Project Class', function() { process.chdir(projPath); // Instantiate Serverless - serverless = new Serverless({ - interactive: false, - projectPath: projPath + serverless = new Serverless( projPath, { + interactive: false }); return serverless.init() .then(function() { // Instantiate Class - instance = new serverless.classes.Project(serverless); + instance = serverless.getProject(); done(); }); @@ -107,7 +106,13 @@ describe('Test Serverless Project Class', function() { }); it('Create new and save', function(done) { - let project = new serverless.classes.Project(serverless); + // TODO: Project creation is an unholy mess now. It currently is done partially outside of Project class, + // split between ServerlessState and Meta classes, ProjectInit action, and ServerlessProject itself. + // So, either the code should be moved fully to Project and be tested here (preferred) + // or not really tested here. To make this happen we should first remove ServerlessState and ServerlessMeta + // classes completely. + let project = new serverless.classes.Project(serverless.getProject().getRootPath()); + project.setServerless( serverless ); project.save() .then(function(instance) { diff --git a/tests/tests/classes/ServerlessStateTest.js b/tests/tests/classes/ServerlessStateTest.js index 0059f657b..b18135188 100644 --- a/tests/tests/classes/ServerlessStateTest.js +++ b/tests/tests/classes/ServerlessStateTest.js @@ -25,9 +25,7 @@ describe('Test Serverless State Class', function() { process.chdir(projPath); // Instantiate Serverless - let project = new Project( projPath ); - project.load(); - serverless = new Serverless( project, { + serverless = new Serverless( projPath, { interactive: false }); From 24b9d73bfbc4251c191c43b588b6d1feb5ff56d1 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Wed, 10 Feb 2016 14:07:42 +0100 Subject: [PATCH 14/17] ServerlessRuntime class hierarchy introduced --- lib/Serverless.js | 2 +- lib/ServerlessComponent.js | 63 +++++++++++------------ lib/ServerlessFunction.js | 30 +++-------- lib/actions/CodeDeployLambda.js | 2 +- lib/actions/ComponentCreate.js | 23 ++------- lib/actions/FunctionRun.js | 12 +---- lib/actions/ProjectInit.js | 21 +++----- lib/runtimes/ServerlessBaseRuntime.js | 55 ++++++++++++++++++++ lib/runtimes/ServerlessNodeRuntime.js | 40 ++++++++++++++ lib/runtimes/ServerlessPython27Runtime.js | 58 +++++++++++++++++++++ lib/utils/index.js | 23 ++------- 11 files changed, 207 insertions(+), 122 deletions(-) create mode 100644 lib/runtimes/ServerlessBaseRuntime.js create mode 100644 lib/runtimes/ServerlessNodeRuntime.js create mode 100644 lib/runtimes/ServerlessPython27Runtime.js diff --git a/lib/Serverless.js b/lib/Serverless.js index e1fafef41..ee4b01ae5 100644 --- a/lib/Serverless.js +++ b/lib/Serverless.js @@ -40,7 +40,7 @@ class Serverless { }; this.classes = { - // TODO: add Runtime, Stage, Region + // TODO: add Stage, Region State: require('./ServerlessState'), Meta: require('./ServerlessMeta'), Project: require('./ServerlessProject'), diff --git a/lib/ServerlessComponent.js b/lib/ServerlessComponent.js index a4d71fbfe..3253d453b 100644 --- a/lib/ServerlessComponent.js +++ b/lib/ServerlessComponent.js @@ -29,10 +29,27 @@ class ServerlessComponent { // Default Properties _this.name = _this._config.sPath || 'component' + SUtils.generateShortId(6); - _this.runtime = config.runtime || 'nodejs'; _this.custom = {}; _this.functions = {}; _this.templates = {}; + + _this.setRuntime( config.runtime || 'nodejs' ); + } + + getRuntime() { + return this._runtime; + } + + setRuntime( runtimeName ) { + let runtime = SUtils.supportedRuntimes[ runtimeName ]; + + if( runtime ) { + // TODO: get rid of that set()/get()/_.assign/_.cloneDeep so this can be cleaner + this.runtime = runtimeName; + this._runtime = new runtime( this._S ); + } else { + throw new SError( `Runtime ${runtimeName} is not supported!` ); + } } /** @@ -155,6 +172,9 @@ class ServerlessComponent { .then(function() { // Merge + _this.setRuntime( componentJson.runtime ); + delete componentJson.runtime; + _.assign(_this, componentJson); return _this; }); @@ -183,6 +203,9 @@ class ServerlessComponent { } // Merge in + _this.setRuntime( data.runtime ); + delete data.runtime; + _this = _.extend(_this, data); return _this; } @@ -302,40 +325,14 @@ class ServerlessComponent { */ _create() { + let _this = this; - let _this = this, - writeDeferred = []; + return BbPromise.try(function() { + fs.mkdirSync(_this._config.fullPath); + fs.mkdirSync(path.join(_this._config.fullPath, 'lib')); - return BbPromise.try(function() { - - writeDeferred.push( - fs.mkdirSync(_this._config.fullPath), - fs.mkdirSync(path.join(_this._config.fullPath, 'lib')) - ); - // Runtime: nodejs - if (_this.runtime === 'nodejs') { - let packageJsonTemplate = SUtils.readAndParseJsonSync(path.join(_this._S.config.serverlessPath, 'templates', 'nodejs', 'package.json')), - libJs = fs.readFileSync(path.join(_this._S.config.serverlessPath, 'templates', 'nodejs', 'index.js')); - - writeDeferred.push( - SUtils.writeFile(path.join(_this._config.fullPath, 'lib', 'index.js'), libJs), - SUtils.writeFile(path.join(_this._config.fullPath, 'package.json'), JSON.stringify(packageJsonTemplate, null, 2)) - ); - } else if (_this.runtime === 'python2.7') { - let requirements = fs.readFileSync(path.join(_this._S.config.serverlessPath, 'templates', 'python2.7', 'requirements.txt')), - initPy = fs.readFileSync(path.join(_this._S.config.serverlessPath, 'templates', 'python2.7', '__init__.py')), - blankInitPy = fs.readFileSync(path.join(_this._S.config.serverlessPath, 'templates', 'python2.7', 'blank__init__.py')); - - writeDeferred.push( - fs.mkdirSync(path.join(_this._config.fullPath, 'vendored')), - SUtils.writeFile(path.join(_this._config.fullPath, 'lib', '__init__.py'), initPy), - SUtils.writeFile(path.join(_this._config.fullPath, 'vendored', '__init__.py'), blankInitPy), - SUtils.writeFile(path.join(_this._config.fullPath, 'requirements.txt'), requirements) - ); - } - - return BbPromise.all(writeDeferred); - }); + return( _this.getRuntime().populateComponentFolder( _this._config.fullPath ) ); + }); } /** diff --git a/lib/ServerlessFunction.js b/lib/ServerlessFunction.js index a0cb3fb9a..a20689ddc 100644 --- a/lib/ServerlessFunction.js +++ b/lib/ServerlessFunction.js @@ -380,31 +380,13 @@ class ServerlessFunction { _create() { return fs.mkdirAsync(this._config.fullPath).then(() => { - let writeDeferred = [], - subFolderLevel = this._config.sPath.split('/').length - 1, + let subFolderLevel = this._config.sPath.split('/').length - 1, fnRootPath = _.repeat('../', subFolderLevel); - writeDeferred.push(SUtils.writeFile(path.join(this._config.fullPath, 'event.json'), '{}')); - - if (this.getRuntime() === 'nodejs') { - writeDeferred.push( - fs.readFileAsync(path.join(this._S.config.serverlessPath, 'templates', 'nodejs', 'handler.js')) - .then((template) => { - let handler = _.template(template)({fnRootPath: fnRootPath}); - return SUtils.writeFile(path.join(this._config.fullPath, 'handler.js'), handler); - }) - ) - } else if (this.getRuntime() === 'python2.7') { - writeDeferred.push( - fs.readFileAsync(path.join(this._S.config.serverlessPath, 'templates', 'python2.7', 'handler.py')) - .then((template) => { - let handler = _.template(template)({fnRootPath: fnRootPath}); - return SUtils.writeFile(path.join(this._config.fullPath, 'handler.py'), handler); - }) - ) - } - return BbPromise.all(writeDeferred); - + return BbPromise.all([ + SUtils.writeFile(path.join(this._config.fullPath, 'event.json'), '{}'), + this.getRuntime().populateFunctionFolder( fnRootPath, this._config.fullPath ) + ]); }); } @@ -412,7 +394,7 @@ class ServerlessFunction { let _this = this; let component = _this._S.state.getComponents({ paths: [_this._config.sPath] })[0]; if (!component) throw new SError('The component containing runtime information for this function could not be found'); - return component.runtime; + return component.getRuntime(); } /** diff --git a/lib/actions/CodeDeployLambda.js b/lib/actions/CodeDeployLambda.js index d3f7b82b6..ccb41d2c1 100644 --- a/lib/actions/CodeDeployLambda.js +++ b/lib/actions/CodeDeployLambda.js @@ -225,7 +225,7 @@ module.exports = function(SPlugin, serverlessPath) { FunctionName: _this.functionName, /* required */ Handler: _this.function.handler, /* required */ Role: _this.meta.stages[_this.evt.options.stage].regions[_this.evt.options.region].variables.iamRoleArnLambda, /* required */ - Runtime: _this.function.getRuntime(), /* required */ + Runtime: _this.function.getRuntime().getName(), /* required */ Description: 'Serverless Lambda function for project: ' + _this.project.name, MemorySize: _this.function.memorySize, Publish: true, // Required by Serverless Framework & recommended best practice by AWS diff --git a/lib/actions/ComponentCreate.js b/lib/actions/ComponentCreate.js index f03f1e599..9400fffbc 100644 --- a/lib/actions/ComponentCreate.js +++ b/lib/actions/ComponentCreate.js @@ -27,8 +27,8 @@ module.exports = function(SPlugin, serverlessPath) { class ComponentCreate extends SPlugin { - constructor(S, config) { - super(S, config); + constructor(S) { + super(S); } static getName() { @@ -180,23 +180,8 @@ usage: serverless component create`, * Install Component Dependencies */ - _installComponentDependencies() { - let _this = this; - if (_this.evt.options.runtime === 'nodejs') { - SCli.log('Installing "serverless-helpers" for this component via NPM...'); - SCli.log(`-----------------`); - SUtils.npmInstall(this.S.getProject().getFilePath(this.evt.options.sPath)); - SCli.log(`-----------------`); - } else if (_this.evt.options.runtime === 'python2.7') { - SCli.log("Installing default python dependencies with pip..."); - SCli.log(`-----------------`); - SUtils.pipPrefixInstall( - this.S.getProject().getFilePath(this.evt.options.sPath, 'requirements.txt'), - this.S.getProject().getFilePath(this.evt.options.sPath, 'vendored') - ); - SCli.log(`-----------------`); - } - return BbPromise.resolve(); + _installComponentDependencies(component) { + return( component.getRuntime().installDepedencies( this.evt.options.sPath ) ); } } diff --git a/lib/actions/FunctionRun.js b/lib/actions/FunctionRun.js index 79b63bf13..f7afaf526 100644 --- a/lib/actions/FunctionRun.js +++ b/lib/actions/FunctionRun.js @@ -136,7 +136,7 @@ module.exports = function(SPlugin, serverlessPath) { _runLocal() { let _this = this, - runtime = _this.function.getComponent().runtime; + runtime = _this.function.getComponent().getRuntime(); let newOptions = { options: { @@ -145,15 +145,7 @@ module.exports = function(SPlugin, serverlessPath) { }; return BbPromise.try(function() { - - // Runtime: nodejs - if (runtime === 'nodejs') { - return _this.S.actions.functionRunLambdaNodeJs(newOptions); - } else if (runtime === 'python2.7') { - return _this.S.actions.functionRunLambdaPython2(newOptions); - } else { - return BbPromise.reject(new SError(`Only nodejs runtime is supported.`)); - } + return _this.S.actions[ runtime.getFunctionRunActionName() ](newOptions); }) .then(function(evt) { _this.evt.data.result = evt.data.result; diff --git a/lib/actions/ProjectInit.js b/lib/actions/ProjectInit.js index 260594939..8923d417e 100644 --- a/lib/actions/ProjectInit.js +++ b/lib/actions/ProjectInit.js @@ -488,22 +488,13 @@ module.exports = function(SPlugin, serverlessPath) { let _this = this, components = _this.S.state.getComponents(); - return BbPromise.try(function() { - - components.forEach(function (component) { + return BbPromise.all( + components.map(function (component) { SCli.log(`Installing ${component.runtime} dependencies for component: ${component.name}...`); - if (component.runtime === 'nodejs') { - SUtils.npmInstall(_this.S.getProject().getFilePath( component.name )); - } else if (component.runtime === 'python2.7') { - SUtils.pipPrefixInstall( - _this.S.getProject().getFilePath( component.name, 'requirements.txt' ), - _this.S.getProject().getFilePath( component.name, 'vendored' ) - ); - } - return BbPromise.resolve(); - - }); - }) + component.getRuntime().installDepedencies( component.name ); //TODO: shouldnt we use component sPath, in case it is a subfolder? + }), + { concurrency: 1 } + ); } } diff --git a/lib/runtimes/ServerlessBaseRuntime.js b/lib/runtimes/ServerlessBaseRuntime.js new file mode 100644 index 000000000..1794c2bc4 --- /dev/null +++ b/lib/runtimes/ServerlessBaseRuntime.js @@ -0,0 +1,55 @@ +'use strict'; + +const SError = require('../ServerlessError'), + BbPromise = require('bluebird'), + SUtils = require('../utils/index'), + fs = require('fs'), + path = require('path'); + +/** + * This is the base class that all Serverless Runtimes should extend. + */ + +class ServerlessBaseRuntime { + constructor(S, name) { + this.S = S; + this.name = name; + } + + populateComponentFolder( componentPath ) { + return BbPromise.reject(new SError(`Runtime ${this.name} should implement populateComponentFolder()`)); + } + + populateFunctionFolder( fnRootPath, fnFullPath ) { + return BbPromise.reject(new SError(`Runtime ${this.name} should implement populateFunctionFolder()`)); + } + + installDepedencies( dir ) { + return BbPromise.reject(new SError(`Runtime ${this.name} should implement installDepedencies()`)); + } + + getFunctionRunActionName() { + throw new SError(`Runtime ${this.name} should implement getFunctionRunAction()`); + } + + // Helper methods for derived classes + + getName(){ + return this.name; + } + + copyFileFromTemplate(from, to, transform) { + from = path.join.apply( path, from ); + to = path.join.apply( path, to ); + + let content = fs.readFileSync(path.join(this.S.config.serverlessPath, 'templates', this.name, from)); + + if( transform ){ + content = transform( content ); + } + + SUtils.writeFile(to, content); + }; +} + +module.exports = ServerlessBaseRuntime; diff --git a/lib/runtimes/ServerlessNodeRuntime.js b/lib/runtimes/ServerlessNodeRuntime.js new file mode 100644 index 000000000..848eeb5bc --- /dev/null +++ b/lib/runtimes/ServerlessNodeRuntime.js @@ -0,0 +1,40 @@ +'use strict'; + +const SError = require('../ServerlessError'), + BaseRuntime = require('./ServerlessBaseRuntime'), + SCli = require('../utils/cli'), + SUtils = require('../utils/index'), + _ = require('lodash'), + BbPromise = require('bluebird'); + +class ServerlessNodeRuntime extends BaseRuntime { + constructor(S) { + super( S, 'nodejs' ); + } + + populateComponentFolder( componentPath ) { + BbPromise.all([ + this.copyFileFromTemplate( [ 'index.js' ], [ componentPath, 'lib', 'index.js' ] ), + this.copyFileFromTemplate( [ 'package.json' ], [ componentPath, 'package.json' ] ) + ]); + } + + populateFunctionFolder( fnRootPath, fnFullPath ) { + this.copyFileFromTemplate( [ 'handler.js' ], [ fnFullPath, 'handler.js' ], function(template){ + return _.template(template)({fnRootPath: fnRootPath}); + } ); + } + + getFunctionRunActionName() { + return 'functionRunLambdaNodeJs'; + } + + installDepedencies( dir ) { + SCli.log('Installing "serverless-helpers" for this component via NPM...'); + SCli.log(`-----------------`); + SUtils.npmInstall(this.S.getProject().getFilePath(dir)); + SCli.log(`-----------------`); + } +} + +module.exports = ServerlessNodeRuntime; diff --git a/lib/runtimes/ServerlessPython27Runtime.js b/lib/runtimes/ServerlessPython27Runtime.js new file mode 100644 index 000000000..a66004a67 --- /dev/null +++ b/lib/runtimes/ServerlessPython27Runtime.js @@ -0,0 +1,58 @@ +'use strict'; + +const SError = require('../ServerlessError'), + SCli = require('../utils/cli'), + BaseRuntime = require('./ServerlessBaseRuntime'), + BbPromise = require('bluebird'), + path = require('path'), + _ = require('lodash'), + fs = require('fs'); + +/** + * Pip install using prefix strategy (not virtualenv), requires a modern `pip` version + */ +function pipPrefixInstall(requirements, dir) { + if (exec(`pip install -t "${dir}" -r "${requirements}"`, { silent: false }).code !== 0) { + throw new SError(`Error executing pip install on ${dir}`, SError.errorCodes.UNKNOWN); + } + + process.chdir(process.cwd()); +}; + +class ServerlessPython27Runtime extends BaseRuntime { + constructor(S) { + super( S, 'python2.7' ); + } + + populateComponentFolder( componentPath ) { + fs.mkdirSync(path.join( componentPath, 'vendored')); + + BbPromise.all([ + this.copyFileFromTemplate( [ '__init__.py' ], [ componentPath, 'lib', '__init__.py' ]), + this.copyFileFromTemplate( [ 'blank__init__.py' ], [ componentPath, 'vendored', '__init__.py' ] ), + this.copyFileFromTemplate( [ 'requirements.txt' ], [ componentPath, 'requirements.txt' ] ) + ]); + } + + populateFunctionFolder( fnRootPath, fnFullPath ) { + this.copyFileFromTemplate( [ 'handler.py' ], [ fnFullPath, 'handler.py' ], function(template){ + return _.template(template)({fnRootPath: fnRootPath}); + } ); + } + + getFunctionRunActionName() { + return 'functionRunLambdaPython2'; + } + + installDepedencies( dir ) { + SCli.log("Installing default python dependencies with pip..."); + SCli.log(`-----------------`); + pipPrefixInstall( + this.S.getProject().getFilePath( dir, 'requirements.txt'), + this.S.getProject().getFilePath( dir, 'vendored') + ); + SCli.log(`-----------------`); + } +} + +module.exports = ServerlessPython27Runtime; diff --git a/lib/utils/index.js b/lib/utils/index.js index adfe23908..094a32a55 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -25,14 +25,8 @@ BbPromise.promisifyAll(fs); */ module.exports.supportedRuntimes = { - "nodejs": { - defaultPkgMgr: 'npm', - validPkgMgrs: ['npm'] - }, - "python2.7": { - defaultPkgMgr: 'pip', - validPkgMgrs: ['pip'] - } + "nodejs": require('../runtimes/ServerlessNodeRuntime'), + "python2.7": require('../runtimes/ServerlessPython27Runtime') }; /** @@ -400,6 +394,8 @@ exports.endsWith = function(str, suffix) { /** * NPM Install * - Programatically install NPM dependencies + * + * This function is here only for purpose of running testsuite. */ exports.npmInstall = function(dir) { @@ -412,17 +408,6 @@ exports.npmInstall = function(dir) { process.chdir(process.cwd()); }; -/** - * Pip install using prefix strategy (not virtualenv), requires a modern `pip` version - */ -exports.pipPrefixInstall = function(requirements, dir) { - if (exec(`pip install -t "${dir}" -r "${requirements}"`, { silent: false }).code !== 0) { - throw new SError(`Error executing pip install on ${dir}`, SError.errorCodes.UNKNOWN); - } - - process.chdir(process.cwd()); -}; - /** * Write to console.log if process.env.DEBUG is true * - If we ever want to get more complicated with log levels we should use winston From 107cc6b5d254f9610fccd31260bdecb7cab565eb Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Thu, 11 Feb 2016 08:47:35 +0100 Subject: [PATCH 15/17] Renamed Runtime classes --- ...erlessBaseRuntime.js => ServerlessRuntimeBase.js} | 8 ++++---- ...erlessNodeRuntime.js => ServerlessRuntimeNode.js} | 12 ++++++------ ...thon27Runtime.js => ServerlessRuntimePython27.js} | 10 +++++----- lib/utils/index.js | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) rename lib/{runtimes/ServerlessBaseRuntime.js => ServerlessRuntimeBase.js} (88%) rename lib/{runtimes/ServerlessNodeRuntime.js => ServerlessRuntimeNode.js} (77%) rename lib/{runtimes/ServerlessPython27Runtime.js => ServerlessRuntimePython27.js} (87%) diff --git a/lib/runtimes/ServerlessBaseRuntime.js b/lib/ServerlessRuntimeBase.js similarity index 88% rename from lib/runtimes/ServerlessBaseRuntime.js rename to lib/ServerlessRuntimeBase.js index 1794c2bc4..520d2fc37 100644 --- a/lib/runtimes/ServerlessBaseRuntime.js +++ b/lib/ServerlessRuntimeBase.js @@ -1,8 +1,8 @@ 'use strict'; -const SError = require('../ServerlessError'), +const SError = require('./ServerlessError'), BbPromise = require('bluebird'), - SUtils = require('../utils/index'), + SUtils = require('./utils/index'), fs = require('fs'), path = require('path'); @@ -10,7 +10,7 @@ const SError = require('../ServerlessError'), * This is the base class that all Serverless Runtimes should extend. */ -class ServerlessBaseRuntime { +class ServerlessRuntimeBase { constructor(S, name) { this.S = S; this.name = name; @@ -52,4 +52,4 @@ class ServerlessBaseRuntime { }; } -module.exports = ServerlessBaseRuntime; +module.exports = ServerlessRuntimeBase; diff --git a/lib/runtimes/ServerlessNodeRuntime.js b/lib/ServerlessRuntimeNode.js similarity index 77% rename from lib/runtimes/ServerlessNodeRuntime.js rename to lib/ServerlessRuntimeNode.js index 848eeb5bc..0489bab9e 100644 --- a/lib/runtimes/ServerlessNodeRuntime.js +++ b/lib/ServerlessRuntimeNode.js @@ -1,13 +1,13 @@ 'use strict'; -const SError = require('../ServerlessError'), - BaseRuntime = require('./ServerlessBaseRuntime'), - SCli = require('../utils/cli'), - SUtils = require('../utils/index'), +const SError = require('./ServerlessError'), + RuntimeBase = require('./ServerlessRuntimeBase'), + SCli = require('./utils/cli'), + SUtils = require('./utils/index'), _ = require('lodash'), BbPromise = require('bluebird'); -class ServerlessNodeRuntime extends BaseRuntime { +class ServerlessRuntimeNode extends RuntimeBase { constructor(S) { super( S, 'nodejs' ); } @@ -37,4 +37,4 @@ class ServerlessNodeRuntime extends BaseRuntime { } } -module.exports = ServerlessNodeRuntime; +module.exports = ServerlessRuntimeNode; diff --git a/lib/runtimes/ServerlessPython27Runtime.js b/lib/ServerlessRuntimePython27.js similarity index 87% rename from lib/runtimes/ServerlessPython27Runtime.js rename to lib/ServerlessRuntimePython27.js index a66004a67..17be55b87 100644 --- a/lib/runtimes/ServerlessPython27Runtime.js +++ b/lib/ServerlessRuntimePython27.js @@ -1,8 +1,8 @@ 'use strict'; -const SError = require('../ServerlessError'), - SCli = require('../utils/cli'), - BaseRuntime = require('./ServerlessBaseRuntime'), +const SError = require('./ServerlessError'), + SCli = require('./utils/cli'), + RuntimeBase = require('./ServerlessRuntimeBase'), BbPromise = require('bluebird'), path = require('path'), _ = require('lodash'), @@ -19,7 +19,7 @@ function pipPrefixInstall(requirements, dir) { process.chdir(process.cwd()); }; -class ServerlessPython27Runtime extends BaseRuntime { +class ServerlessRuntimePython27 extends RuntimeBase { constructor(S) { super( S, 'python2.7' ); } @@ -55,4 +55,4 @@ class ServerlessPython27Runtime extends BaseRuntime { } } -module.exports = ServerlessPython27Runtime; +module.exports = ServerlessRuntimePython27; diff --git a/lib/utils/index.js b/lib/utils/index.js index 094a32a55..08cb1cd76 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -25,8 +25,8 @@ BbPromise.promisifyAll(fs); */ module.exports.supportedRuntimes = { - "nodejs": require('../runtimes/ServerlessNodeRuntime'), - "python2.7": require('../runtimes/ServerlessPython27Runtime') + "nodejs": require('../ServerlessRuntimeNode'), + "python2.7": require('../ServerlessRuntimePython27') }; /** From f6a0a6aa8474c3c97dda7b013455148431b59f44 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Thu, 11 Feb 2016 09:42:07 +0100 Subject: [PATCH 16/17] Updates after merge to 0.5, minor code cleanups. --- lib/ServerlessFunction.js | 2 +- lib/actions/CodeDeployLambda.js | 2 +- lib/actions/CodePackageLambda.js | 2 +- lib/actions/DashDeploy.js | 2 +- lib/actions/EndpointBuildApiGateway.js | 2 +- lib/actions/EndpointDeploy.js | 2 +- lib/actions/FunctionDeploy.js | 2 +- lib/actions/ProjectRemove.js | 2 +- lib/actions/RegionCreate.js | 4 ++-- lib/actions/RegionRemove.js | 2 +- lib/actions/ResourcesDeploy.js | 4 ++-- lib/actions/ResourcesRemove.js | 2 +- tests/tests/actions/ProjectRemove.js | 5 ++--- 13 files changed, 16 insertions(+), 17 deletions(-) diff --git a/lib/ServerlessFunction.js b/lib/ServerlessFunction.js index 34b4a9204..01860467e 100644 --- a/lib/ServerlessFunction.js +++ b/lib/ServerlessFunction.js @@ -233,7 +233,7 @@ class ServerlessFunction { throw new SError(`Stage and region options are required`); } - let name = this.getProject().name + '-' + this.getComponent().name; + let name = this.getProject().getName() + '-' + this.getComponent().name; // Backwards Compatibility Support // TODO: Remove in V1 because will result in breaking change diff --git a/lib/actions/CodeDeployLambda.js b/lib/actions/CodeDeployLambda.js index 9a1295259..4c3ab2504 100644 --- a/lib/actions/CodeDeployLambda.js +++ b/lib/actions/CodeDeployLambda.js @@ -116,7 +116,7 @@ module.exports = function(SPlugin, serverlessPath) { // Instantiate Classes _this.meta = _this.S.state.getMeta(); - _this.project = _this.S.state.getProject(); + _this.project = _this.S.getProject(); _this.function = _this.S.state.getFunctions({ paths: [_this.evt.options.path] })[0]; // Set default function name diff --git a/lib/actions/CodePackageLambda.js b/lib/actions/CodePackageLambda.js index ca74da297..d62fa9d56 100644 --- a/lib/actions/CodePackageLambda.js +++ b/lib/actions/CodePackageLambda.js @@ -95,7 +95,7 @@ module.exports = function(SPlugin, serverlessPath) { // Instantiate classes _this.meta = _this.S.state.getMeta(); - _this.project = _this.S.state.getProject(); + _this.project = _this.S.getProject(); _this.function = _this.S.state.getFunctions({ paths: [_this.evt.options.path] })[0]; if (!_this.function) BbPromise.reject(new SError(`Function could not be found: ${_this.evt.options.path}`)); diff --git a/lib/actions/DashDeploy.js b/lib/actions/DashDeploy.js index e064250a7..f7f9f0ce4 100644 --- a/lib/actions/DashDeploy.js +++ b/lib/actions/DashDeploy.js @@ -113,7 +113,7 @@ module.exports = function(SPlugin, serverlessPath) { _this.evt.data.deployedEndpoints = {}; // Instantiate Classes - _this.project = _this.S.state.getProject(); + _this.project = _this.S.getProject(); _this.meta = _this.S.state.getMeta(); // Flow diff --git a/lib/actions/EndpointBuildApiGateway.js b/lib/actions/EndpointBuildApiGateway.js index 92359b5d0..2c5d942c8 100644 --- a/lib/actions/EndpointBuildApiGateway.js +++ b/lib/actions/EndpointBuildApiGateway.js @@ -124,7 +124,7 @@ module.exports = function(SPlugin, serverlessPath) { let _this = this; // Instantiate Classes - _this.project = _this.S.state.getProject(); + _this.project = _this.S.getProject(); _this.meta = _this.S.state.getMeta(); // If no iamRoleLambda, throw error diff --git a/lib/actions/EndpointDeploy.js b/lib/actions/EndpointDeploy.js index 3a9861ae8..0a0a28243 100644 --- a/lib/actions/EndpointDeploy.js +++ b/lib/actions/EndpointDeploy.js @@ -162,7 +162,7 @@ module.exports = function(SPlugin, serverlessPath) { let _this = this; // Instantiate Classes - _this.project = _this.S.state.getProject(); + _this.project = _this.S.getProject(); _this.meta = _this.S.state.getMeta(); // Set defaults diff --git a/lib/actions/FunctionDeploy.js b/lib/actions/FunctionDeploy.js index 19d164e1d..69a206f92 100644 --- a/lib/actions/FunctionDeploy.js +++ b/lib/actions/FunctionDeploy.js @@ -172,7 +172,7 @@ module.exports = function(SPlugin, serverlessPath) { _this.evt.options.aliasFunction = _this.evt.options.aliasFunction ? _this.evt.options.aliasFunction : null; // Instantiate Classes - _this.project = _this.S.state.getProject(); + _this.project = _this.S.getProject(); _this.meta = _this.S.state.getMeta(); // Set Deploy Regions diff --git a/lib/actions/ProjectRemove.js b/lib/actions/ProjectRemove.js index 47ae5097d..0f803e2f3 100644 --- a/lib/actions/ProjectRemove.js +++ b/lib/actions/ProjectRemove.js @@ -63,7 +63,7 @@ usage: serverless project remove`, // Flow return this._removeAllStages() .then(() => { - let projectName = this.S.state.getProject().name; + let projectName = this.S.getProject().getName(); // Status SCli.log(`Successfully removed project "${projectName}"`); diff --git a/lib/actions/RegionCreate.js b/lib/actions/RegionCreate.js index ecc5e2874..bb575cbc1 100644 --- a/lib/actions/RegionCreate.js +++ b/lib/actions/RegionCreate.js @@ -217,11 +217,11 @@ usage: serverless region create`, // Create ENV file in new region let envFileContents = `SERVERLESS_STAGE=${this.evt.options.stage} SERVERLESS_DATA_MODEL_STAGE=${this.evt.options.stage} -SERVERLESS_PROJECT_NAME=${this.S.state.getProject().name}`; +SERVERLESS_PROJECT_NAME=${this.S.getProject().name}`; return this.S3.sPutEnvFile( this.S.state.getMeta().variables.projectBucket, - this.S.state.getProject().name, + this.S.getProject().name, this.evt.options.stage, this.evt.options.region, envFileContents); diff --git a/lib/actions/RegionRemove.js b/lib/actions/RegionRemove.js index ea5ad064b..22a146fbc 100644 --- a/lib/actions/RegionRemove.js +++ b/lib/actions/RegionRemove.js @@ -161,7 +161,7 @@ usage: serverless region remove`, _listS3Objects() { SUtils.sDebug("List related S3 objects"); - let prefix = ['serverless', this.S.state.getProject().name, this.evt.options.stage, this.evt.options.region].join('/'), + let prefix = ['serverless', this.S.getProject().name, this.evt.options.stage, this.evt.options.region].join('/'), params = { Bucket: this.S.state.getMeta().variables.projectBucket, Prefix: prefix diff --git a/lib/actions/ResourcesDeploy.js b/lib/actions/ResourcesDeploy.js index 3e24201ef..aca495c49 100644 --- a/lib/actions/ResourcesDeploy.js +++ b/lib/actions/ResourcesDeploy.js @@ -208,7 +208,7 @@ usage: serverless resources deploy`, // Upload to S3 Bucket return _this.S3.sPutCfFile( _this.S.state.getMeta().variables.projectBucket, - _this.S.state.getProject().name, + _this.S.getProject().getName(), _this.evt.options.stage, _this.evt.options.region, _this.cfTemplate @@ -217,7 +217,7 @@ usage: serverless resources deploy`, // Trigger CF Stack Create/Update return _this.CF.sCreateOrUpdateResourcesStack( - _this.S.state.getProject().name, + _this.S.getProject().getName(), _this.evt.options.stage, _this.evt.options.region, regionVars.resourcesStackName ? regionVars.resourcesStackName : null, diff --git a/lib/actions/ResourcesRemove.js b/lib/actions/ResourcesRemove.js index 7c98ce01a..2717da6bf 100644 --- a/lib/actions/ResourcesRemove.js +++ b/lib/actions/ResourcesRemove.js @@ -159,7 +159,7 @@ usage: serverless resources remove`, region = _this.evt.options.region, regionVars = _this.S.state.getMeta().stages[stage].regions[region].variables, projectBucket = _this.S.state.getMeta().variables.projectBucket, - projectName = _this.S.state.getProject().name; + projectName = _this.S.getProject().getName(); // Config AWS Services let awsConfig = { diff --git a/tests/tests/actions/ProjectRemove.js b/tests/tests/actions/ProjectRemove.js index bdbda81b3..2cccc3f42 100644 --- a/tests/tests/actions/ProjectRemove.js +++ b/tests/tests/actions/ProjectRemove.js @@ -37,11 +37,10 @@ describe('Test Action: Project Remove', function() { this.timeout(0); process.chdir(projPath); // Ror some weird reason process.chdir adds /private/ before cwd path - serverless = new Serverless({ + serverless = new Serverless( projPath, { interactive: false, awsAdminKeyId: config.awsAdminKeyId, - awsAdminSecretKey: config.awsAdminSecretKey, - projectPath: projPath + awsAdminSecretKey: config.awsAdminSecretKey }); return serverless.state.load().then(function() { From ce53edc2afc76ef81c597aa275c3bd03bf3d68e7 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Thu, 11 Feb 2016 09:51:41 +0100 Subject: [PATCH 17/17] Bugfix + cleanup --- lib/ServerlessMeta.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/ServerlessMeta.js b/lib/ServerlessMeta.js index c94f7453f..554982085 100644 --- a/lib/ServerlessMeta.js +++ b/lib/ServerlessMeta.js @@ -51,8 +51,6 @@ class ServerlessMeta // Skip unrelated and hidden files if (!variableFiles[i] || variableFiles[i].charAt(0) === '.' || variableFiles[i].indexOf('s-variables') == -1) continue; - let variableFile = SUtils.readAndParseJsonSync(getProject().getFilePath('_meta', 'variables', variableFiles[i])); - // Parse file name to get stage/region let file = variableFiles[i].replace('s-variables-', '').replace('.json', '');