ServerlessState: Enhance get methods to use more than serverless paths to query serverless assets

This commit is contained in:
ac360 2016-01-16 10:54:14 -08:00
parent 39d8c40764
commit 0b88cf232b
4 changed files with 249 additions and 192 deletions

View File

@ -98,10 +98,10 @@ class ServerlessState {
};
return this.project.getPopulated(options)
.then(function(data) {
populatedData.project = data;
return populatedData;
});
.then(function(data) {
populatedData.project = data;
return populatedData;
});
}
/**
@ -134,8 +134,8 @@ class ServerlessState {
if (options.populate) {
return this.getPopulated(options)
.then(function(populatedData) {
return SUtils.getResources(populatedData.project);
});
return SUtils.getResources(populatedData.project);
});
} else {
return Promise.resolve(SUtils.getResources(this.project.get()));
}
@ -161,248 +161,261 @@ class ServerlessState {
/**
* Get Components
* - returns an array of this state's project component instances
* - Returns an array of this state's project component instances
* - Options: component
* - options.paths is an array of serverless paths like this: ['component', 'component']
*/
getComponents(options) {
let _this = this,
pathsObj = {},
components = [];
options = options || {};
// If paths, create temp obj for easy referencing
if (options.paths && options.paths.length) {
options.paths.forEach(function (path) {
let component = path.split('/')[0];
if (!pathsObj[component]) pathsObj[component] = {};
});
}
let _this = this,
allComponents = [],
foundComponents = [];
// 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]];
// If paths, and this component is not included, skip
if (options.paths &&
options.paths.length &&
!_.get(pathsObj, component.name, false)) continue;
components.push(component);
allComponents.push(_this.project.components[Object.keys(_this.project.components)[i]]);
}
if (options.paths && !components.length) {
throw new SError('No components found in the paths you provided');
// Return if no options specified
if (!options) return allComponents;
// If options specified, loop through and find the ones specified
for (let i = 0; i < allComponents.length; i++) {
let component = allComponents[i];
if (options.component) {
if (component._config.component == options.component) {
foundComponents.push(component);
}
continue;
}
if (options.paths && options.paths.indexOf(component._config.sPath) !== -1) {
foundComponents.push(component);
continue;
}
}
return components;
if (!foundComponents.length) {
throw new SError('No components found via the options you provided');
}
return foundComponents;
}
/**
* Get Modules
* - returns an array of this state's modules instances
* - Returns an array of this state's modules instances
* - Options: component, module
* - options.paths is an array of serverless paths like this: ['component/moduleOne', 'component/moduleTwo']
*/
getModules(options) {
let _this = this,
pathsObj = {},
modules = [];
options = options || {};
// If paths, create temp obj for easy referencing
if (options.paths && options.paths.length) {
options.paths.forEach(function (path) {
let component = path.split('/')[0];
let module = path.split('/')[1];
if (!pathsObj[component]) pathsObj[component] = {};
if (!pathsObj[component][module]) pathsObj[component][module] = {};
});
}
let _this = this,
allModules = [],
foundModules = [];
// 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]];
// If paths, and this component is not included, skip
if (options.paths &&
options.paths.length &&
!_.get(pathsObj, component.name, false)) continue;
if (!component.modules) continue;
for (let j = 0; j < Object.keys(component.modules).length; j++) {
let module = component.modules[Object.keys(component.modules)[j]];
// If paths, and this component is not included, skip
if (options.paths &&
options.paths.length &&
!_.get(pathsObj, component.name + '.' + module.name, false)) continue;
modules.push(module);
allModules.push(component.modules[Object.keys(component.modules)[j]]);
}
}
if (options.paths && !modules.length) {
throw new SError('No modules found in the paths you provided');
// Return if no options specified
if (!options) return allModules;
// If options specified, loop through and find the ones specified
for (let i = 0; i < allModules.length; i++) {
let module = allModules[i];
if (options.component && options.module) {
if (module._config.component == options.component && module._config.module == options.module) {
foundModules.push(module);
}
continue;
}
if (options.component) {
if (module._config.component == options.component) {
foundModules.push(module);
}
continue;
}
if (options.paths && options.paths.indexOf(module._config.sPath) !== -1) {
foundModules.push(module);
continue;
}
}
return modules;
if (!foundModules.length) {
throw new SError('No modules found via the options you provided');
}
return foundModules;
}
/**
* Get Functions
* - returns an array of this state's function instances
* - Returns an array of this state's function instances
* - Options: paths, component, module, function
* - options.paths is an array of Serverless paths like this: ['component/moduleOne/functionOne', 'component/moduleOne/functionOne']
*/
getFunctions(options) {
let _this = this,
functions = [],
pathsObj = {};
options = options || {};
// If paths, create temp obj for easy referencing
if (options.paths && options.paths.length) {
options.paths.forEach(function (path) {
// Validate Path
SUtils.validateSPath(_this._S.config.projectPath, path, 'function');
var parsed = SUtils.parseSPath(path);
if (!pathsObj[parsed.component]) pathsObj[parsed.component] = {};
if (!pathsObj[parsed.component][parsed.module]) pathsObj[parsed.component][parsed.module] = {};
pathsObj[parsed.component][parsed.module][parsed.function] = true;
});
}
let _this = this,
allFunctions = [],
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]];
// If paths, and this component is not included, skip
if (options.paths &&
options.paths.length &&
!_.get(pathsObj, component.name, false)) continue;
if (!component.modules) continue;
for (let j = 0; j < Object.keys(component.modules).length; j++) {
let module = component.modules[Object.keys(component.modules)[j]];
// If paths, and this component is not included, skip
if (options.paths &&
options.paths.length &&
!_.get(pathsObj, component.name + '.' + module.name, false)) continue;
if (!module.functions) continue;
for (let k = 0; k < Object.keys(module.functions).length; k++) {
let func = module.functions[Object.keys(module.functions)[k]];
// If paths, and this component is not included, skip
if (options.paths &&
options.paths.length &&
!_.get(pathsObj, component.name + '.' + module.name + '.' + func.name, false)) continue;
functions.push(func);
allFunctions.push(module.functions[Object.keys(module.functions)[k]]);
}
}
}
if (options.paths && !functions.length) {
throw new SError('No functions found in the paths you provided');
// Return if no options specified
if (!options) return allFunctions;
// If options specified, loop through and find the ones specified
for (let i = 0; i < allFunctions.length; i++) {
let func = allFunctions[i];
if (options.component && options.module && options.function) {
if (func._config.component == options.component && func._config.module == options.module && func.name == options.function) {
foundFunctions.push(func);
}
continue;
}
if (options.component && options.module) {
if (func._config.component == options.component && func._config.module == options.module) {
foundFunctions.push(func);
}
continue;
}
if (options.component) {
if (func._config.component == options.component) {
foundFunctions.push(func);
}
continue;
}
if (options.paths && options.paths.indexOf(func._config.sPath) !== -1) {
foundFunctions.push(func);
continue;
}
}
return functions;
if (!foundFunctions.length) {
throw new SError('No functions found via the options you provided');
}
return foundFunctions;
}
/**
* Get Endpoints
* - Returns an array of this state's function instances
* - Options: paths, component, module, function, endpointPath, endpointMethod
* - options.paths is an array of Serverless paths like this: ['component/moduleOne/functionOne@moduleOne/functionOne~GET']
*/
getEndpoints(options) {
let _this = this,
endpoints = [],
pathsObj = {};
options = options || {};
// Get Project Data
let project = options.populate ? _this.getPopulated(options) : _this.get();
// If paths, create temp obj for easy referencing
if (options.paths && options.paths.length) {
options.paths.forEach(function (path) {
SUtils.validateSPath(_this._S.projectPath, path, 'endpoint');
let parsed = SUtils.parseSPath(path);
if (!pathsObj[parsed.component]) pathsObj[parsed.component] = {};
if (!pathsObj[parsed.component][parsed.module]) pathsObj[parsed.component][parsed.module] = {};
if (!pathsObj[parsed.component][parsed.module][parsed.function]) pathsObj[parsed.component][parsed.module][parsed.function] = {};
if (!pathsObj[parsed.component][parsed.module][parsed.function][parsed.urlPath]) pathsObj[parsed.component][parsed.module][parsed.function][parsed.urlPath] = {};
if (!pathsObj[parsed.component][parsed.module][parsed.function][parsed.urlPath][parsed.urlMethod]) pathsObj[parsed.component][parsed.module][parsed.function][parsed.urlPath][parsed.urlMethod] = true;
});
}
let _this = this,
allEndpoints = [],
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]];
// If paths, and this component is not included, skip
if (options.paths &&
options.paths.length &&
!_.get(pathsObj, component.name, false)) continue;
if (!component.modules) continue;
for (let j = 0; j < Object.keys(component.modules).length; j++) {
let module = component.modules[Object.keys(component.modules)[j]];
// If paths, and this component is not included, skip
if (options.paths &&
options.paths.length &&
!_.get(pathsObj, component.name + '.' + module.name, false)) continue;
if (!module.functions) continue;
for (let k = 0; k < Object.keys(module.functions).length; k++) {
let func = module.functions[Object.keys(module.functions)[k]];
for (let l = 0; l < func.endpoints.length; l++) {
let endpoint = func.endpoints[l];
// If paths, and this component is not included, skip
if (options.paths &&
options.paths.length &&
!_.get(pathsObj, component.name + '.' + module.name + '.' + func.name + '.' + endpoint.path + '.' + endpoint.method, false)) continue;
endpoints.push(endpoint);
allEndpoints.push(func.endpoints[l]);
}
}
}
}
if (options.paths && !endpoints.length) {
throw new SError('No endpoints found in the paths you provided');
// Return if no options specified
if (!options) return allEndpoints;
// If options specified, loop through functions and find the ones specified
for (let i = 0; i < allEndpoints.length; i++) {
let endpoint = allEndpoints[i];
if (options.component && options.module && options.function && options.endpointPath && options.endpointMethod) {
if (endpoint._config.component == options.component && endpoint._config.module == options.module && endpoint._config.function == options.function && endpoint.path == options.endpointPath && endpoint.method == options.endpointMethod) {
foundEndpoints.push(endpoint);
}
continue;
}
if (options.component && options.module && options.function && options.endpointPath && !options.endpointMethod) {
if (endpoint._config.component == options.component && endpoint._config.module == options.module && endpoint._config.function == options.function && endpoint.path == options.endpointPath) {
foundEndpoints.push(endpoint);
}
continue;
}
if (options.component && options.module && options.function && options.endpointMethod && !options.endpointPath) {
if (endpoint._config.component == options.component && endpoint._config.module == options.module && endpoint._config.function == options.function && endpoint.method == options.endpointMethod) {
foundEndpoints.push(endpoint);
}
continue;
}
if (options.component && options.module && options.function && !options.endpointPath && !options.endpointMethod) {
if (endpoint._config.component == options.component && endpoint._config.module == options.module && endpoint._config.function == options.function) {
foundEndpoints.push(endpoint);
}
continue;
}
if (options.component && options.module && options.endpointMethod && !options.function && !options.endpointPath) {
if (endpoint._config.component == options.component && endpoint._config.module == options.module && endpoint.method == options.endpointMethod) {
foundEndpoints.push(endpoint);
}
continue;
}
if (options.component && options.module && !options.function && !options.endpointPath && !options.endpointMethod) {
if (endpoint._config.component == options.component && endpoint._config.module == options.module) {
foundEndpoints.push(endpoint);
}
continue;
}
if (options.component && options.endpointMethod && !options.module && !options.function && !options.endpointPath) {
if (endpoint._config.component == options.component && endpoint.method == options.endpointMethod) {
foundEndpoints.push(endpoint);
}
continue;
}
if (options.component && !options.module && !options.function && !options.endpointPath && !options.endpointMethod) {
if (endpoint._config.component == options.component) {
foundEndpoints.push(endpoint);
}
continue;
}
if (options.paths && options.paths.indexOf(endpoint._config.sPath) !== -1) {
foundEndpoints.push(endpoint);
continue;
}
}
return endpoints;
if (!foundEndpoints.length) {
throw new SError('No endpoints found via the options you provided');
}
return foundEndpoints;
}
/**

View File

@ -167,26 +167,27 @@ module.exports = function(SPlugin, serverlessPath) {
_this.evt.options.aliasFunction = _this.evt.options.aliasFunction ? _this.evt.options.aliasFunction : null;
// Instantiate Classes
_this.project = new _this.S.classes.Project(_this.S);
_this.meta = new _this.S.classes.Meta(_this.S);
_this.project = new _this.S.state.getProject();
_this.meta = new _this.S.state.getMeta();
// Set Deploy Regions
_this.regions = _this.evt.options.region ? [_this.evt.options.region] : Object.keys(_this.meta.data.stages[_this.evt.options.stage].regions);
_this.regions = _this.evt.options.region ? [_this.evt.options.region] : _this.S.state.getRegions(_this.evt.options.stage);
if (!_this.evt.options.paths.length) {
let CWD = process.cwd(),
let CWD = process.cwd(),
isComponent = SUtils.fileExistsSync(path.join(CWD, 's-component.json')),
isModule = SUtils.fileExistsSync(path.join(CWD, 's-module.json')),
isFunction = SUtils.fileExistsSync(path.join(CWD, 's-function.json'));
isModule = SUtils.fileExistsSync(path.join(CWD, 's-module.json')),
isFunction = SUtils.fileExistsSync(path.join(CWD, 's-function.json'));
if (isComponent) {
if (isComponent){
let componentName = SUtils.readAndParseJsonSync(path.join(CWD, '..', 's-component.json')).name,
component = new _this.S.classes.Component(_this.S, {component: componentName});
component = _this.S.state.getComponents({ paths: [componentName] });
Object.keys(component.data.modules).forEach(function(moduleName) {
Object.keys(component.modules).forEach(function(moduleName) {
Object.keys(component.data.modules[moduleName].functions).forEach(function(functionName) {
Object.keys(component.modules[moduleName].functions).forEach(function(functionName) {
_this.evt.options.paths.push(componentName + path.sep + moduleName + path.sep + functionName);
@ -194,11 +195,12 @@ module.exports = function(SPlugin, serverlessPath) {
});
} else if (isModule) {
let moduleName = SUtils.readAndParseJsonSync(path.join(CWD, 's-module.json')).name,
componentName = SUtils.readAndParseJsonSync(path.join(CWD, '..', 's-component.json')).name,
componentName = SUtils.readAndParseJsonSync(path.join(CWD, '..', 's-component.json')).name,
component = new _this.S.classes.Component(_this.S, {component: componentName});
Object.keys(component.data.modules[moduleName].functions).forEach(function(functionName) {
Object.keys(component.modules[moduleName].functions).forEach(function(functionName) {
_this.evt.options.paths.push(componentName + path.sep + moduleName + path.sep + functionName);
@ -279,7 +281,7 @@ module.exports = function(SPlugin, serverlessPath) {
return BbPromise.try(function() {
// Nodejs
if (func.data.runtime = 'nodejs') {
if (func.runtime = 'nodejs') {
let newEvt = {
options: {
@ -287,7 +289,7 @@ module.exports = function(SPlugin, serverlessPath) {
region: region,
component: func.config.component,
module: func.config.module,
function: func.data.name
function: func.name
}
};
@ -303,8 +305,8 @@ module.exports = function(SPlugin, serverlessPath) {
component: result.options.component,
module: result.options.module,
function: result.options.function,
pathDist: result.data.pathDist,
pathsPackaged: result.data.pathsPackaged
pathDist: result.pathDist,
pathsPackaged: result.pathsPackaged
}
};
@ -321,8 +323,8 @@ module.exports = function(SPlugin, serverlessPath) {
_this.deployed[region].push({
component: func.config.component,
module: func.config.module,
function: func.data.name,
Arn: result.data.lambdaAliasArn
function: func.name,
Arn: result.lambdaAliasArn
});
return cb();
@ -336,7 +338,7 @@ module.exports = function(SPlugin, serverlessPath) {
_this.failed[region].push({
component: func.config.component,
module: func.config.module,
function: func.data.name,
function: func.name,
message: e.message,
stack: e.stack
});

View File

@ -15,7 +15,7 @@ describe('All Tests', function() {
//require('./tests/classes/ServerlessModuleTest');
//require('./tests/classes/ServerlessComponentTest');
//require('./tests/classes/ServerlessProjectTest');
//require('./tests/classes/ServerlessStateTest');
require('./tests/classes/ServerlessStateTest');
//require('./tests/actions/TestPluginCustom');
//require('./tests/actions/TestDefaultActionHook');
//require('./tests/actions/ProjectCreate');
@ -27,7 +27,7 @@ describe('All Tests', function() {
//require('./tests/actions/EnvList');
//require('./tests/actions/EnvGet');
//require('./tests/actions/EnvSetUnset');
require('./tests/actions/ResourcesDeploy');
//require('./tests/actions/ResourcesDeploy');
//require('./tests/actions/FunctionRun');
//require('./tests/actions/FunctionDeploy');
//require('./tests/actions/EndpointDeploy');

View File

@ -147,6 +147,12 @@ describe('Test Serverless State Class', function() {
done();
});
it('Get components by component', function(done) {
let components = instance.getComponents({ component: 'nodejscomponent' });
assert.equal(true, components[0].name === 'nodejscomponent');
done();
});
it('Get modules w/o paths', function(done) {
let modules = instance.getModules();
assert.equal(true, modules[0].name === 'module1');
@ -159,6 +165,18 @@ describe('Test Serverless State Class', function() {
done();
});
it('Get modules by component and module', function(done) {
let modules = instance.getModules({ component: 'nodejscomponent', module: 'module1' });
assert.equal(true, modules[0].name === 'module1');
done();
});
it('Get modules by component', function(done) {
let modules = instance.getModules({ component: 'nodejscomponent' });
assert.equal(true, modules.length === 1);
done();
});
it('Get functions w/o paths', function(done) {
let functions = instance.getFunctions();
assert.equal(true, functions.length === 3);
@ -171,6 +189,12 @@ describe('Test Serverless State Class', function() {
done();
});
it('Get functions by component, module and function', function(done) {
let functions = instance.getFunctions({ component: 'nodejscomponent', module: 'module1', function: 'function1' });
assert.equal(true, functions.length === 1);
done();
});
it('Get endpoints w/o paths', function(done) {
let endpoints = instance.getEndpoints();
assert.equal(true, endpoints.length === 4);
@ -183,6 +207,24 @@ describe('Test Serverless State Class', function() {
done();
});
it('Get endpoints by component, module, function, path and method', function(done) {
let endpoints = instance.getEndpoints({ component: 'nodejscomponent', module: 'module1', function: 'function3', endpointPath: 'module1/function3', endpointMethod: 'POST' });
assert.equal(true, endpoints.length === 1);
done();
});
it('Get endpoints by component, module and function', function(done) {
let endpoints = instance.getEndpoints({ component: 'nodejscomponent', module: 'module1', function: 'function1' });
assert.equal(true, endpoints.length === 1);
done();
});
it('Get endpoints by component and method', function(done) {
let endpoints = instance.getEndpoints({ component: 'nodejscomponent', endpointMethod: 'GET' });
assert.equal(true, endpoints.length === 3);
done();
});
it('Validate stage exists', function(done) {
assert.equal(true, instance.validateStageExists(config.stage));
assert.equal(false, instance.validateStageExists('invalid'));