Skip to content

Commit

Permalink
1. adding 'stubbydb' Command
Browse files Browse the repository at this point in the history
2. Changing the way of handling configuration
3. Adding tests for configuration
4. Adding features to auto scan for configurations and directory structure
5. many design related changes
  • Loading branch information
amitguptagwl committed Mar 13, 2016
1 parent d75de17 commit dd8fcc9
Show file tree
Hide file tree
Showing 18 changed files with 484 additions and 98 deletions.
40 changes: 40 additions & 0 deletions help
@@ -0,0 +1,40 @@
Usage: stubby-db [OPTION]...
Runs stubbyDB server

Arguments
-p, --port port number
-m, --mapping file path of yaml mapping file (response.yaml)
-s, --stub path for stubs only if mapping file has relative path and they are not in current folder
-c, --config name of config file. It must be json file.
-C json config as command line argument
-h, --help display on screen help
-d location of project directory, if it is not a current directory.
-q, --quite Under development
all - turn off on screen logging
info - turn off on screen logging for info only
error - turn off on screen logging for error only

Considerations:
if -p, -m, -s options are given then relevant properties from config file would be ignored;
Precedence of loding config is -p,-m-s > -c > -C > -d > default

Default config:
if no option is given then
1. check for config.json in current folder
2. otherwise check for 'dbsets', 'mappings', 'stubs' folder in currrent directory. and set port to 7777.

Note:
-c, --config The purpose of this option to choose different config file instead of config.json from current directory. But if you specify different location then run stubby-db from that location only. Or maintain absolute paths in config.json for dbsets, mappings, and stubs.

Project directory structure:

Project
|_ dbsets
|_ dumps
|_ mappings
|_ stubs
|_ logs

Read the wiki : https://github.com/NaturalIntelligence/StubbyDB
Report a bug : https://github.com/NaturalIntelligence/StubbyDB/issues

44 changes: 41 additions & 3 deletions index.js
@@ -1,4 +1,42 @@
var stubbyDB = require('./js/stubbyDB').stubbyDB;
#!/usr/bin/env node

var stubby_db = new stubbyDB(7788);
stubby_db.start();
if(process.argv[2] == "--help" || process.argv[2] == "-h"){
console.log();
var fs = require('fs');
console.log(fs.readFileSync("help", 'utf-8'));
console.log();
process.exit(1);
}

var options = {}
for(var i=2; i<process.argv.length;i++){
if(process.argv[i].startsWith("-")){
var key = process.argv[i];
if(key == '--port' || key == '-p'){
key = '-p';
}else if(key == '--config' || key == '-c'){
key = '-c';
}else if(key == '--mapping' || key == '-m'){
key = '-m';
}else if(key == '--stub' || key == '-s'){
key = '-s';
}else if(key == '-C' || key == '-d'){
//key = '-p';
}else{
console.log("Invalid options");
console.log("Try 'stubbydb --help' for more information.*/")
process.exit(1);
}
options[key] = process.argv[++i];
}
}

var configBuilder = require("./js/configbuilder");
configBuilder.buildConfig(options,process.argv.length);
var config = configBuilder.getConfig();
console.log("Configuration: " + JSON.stringify(config));


var stubbyDB = require('./js/stubbyDB');
var server = new stubbyDB();
server.start();
154 changes: 154 additions & 0 deletions js/configbuilder.js
@@ -0,0 +1,154 @@
var fs = require('fs');
var util = require('./preutil');

var defaultConfig = {
mappings: {
default: {
request:{
method: 'GET'
},
response: {
strategy: 'first-found',
latency: 0,
status: 200
}
},
requests: ["response.yaml"]
},
server: {
port: 7777
},
logs:{
path: 'logs'
}
};

/*exports.reset = function(){
var someconfig = {
mappings: {
default: {
request:{
method: 'GET'
},
response: {
strategy: 'first-found',
latency: 0,
status: 200
}
},
request: "response.yaml"
},
server: {
port: 7777
}
};
defaultConfig = someconfig;
}*/

var setConfig = function(path, value) {
var s = defaultConfig;
var pList = path.split('.');
var len = pList.length;
for(var i = 0; i < len-1; i++) {
var elem = pList[i];
if( !s[elem] ) s[elem] = {}
s = s[elem];
}

s[pList[len-1]] = value;
}

exports.buildConfig = function(options,count){

if(count == 2){//No option is provided. Run with default options
useDefaultConfig();
}else if(options['-c']){
var jsonconfig = require(options['-c']);
buildFromJsonConfig(jsonconfig);
}else if(options['-C']){
var jsonConfig;
try{
jsonConfig = JSON.parse(options['-C']);
}catch(e){
console.log("Invalid json");
process.exit(1);
}
buildFromJsonConfig(jsonConfig);
}else if(options['-d']){
buildFromDirectory(options['-d']);
}

if(options['-p']){
setConfig('server.port',options['-p']);
}

if(options['-m']){
defaultConfig.mappings.requests = [];
defaultConfig.mappings.requests.push(options['-m']);
}

if(options['-s']){
setConfig('stubs',options['-s']);
}

}

/*
load config from config.json, if presents.
Otherwise follow current directory structure.
Use default port only.
*/
function useDefaultConfig(){
console.log(process.cwd());
if(util.isExist(process.cwd() + "/config.json")){
var jsonconfig = require(process.cwd() +'/config.json');
buildFromJsonConfig(jsonconfig);
}else{
buildFromDirectory(process.cwd());
}
}

var merge = require('deepmerge');

function buildFromJsonConfig(jsonconfig){
defaultConfig = merge(defaultConfig,jsonconfig);
}

/*
build configurtaion on the basis of directory structure
It'll ignore if there is any config file in specified directory.
It update the path of : mappings, dbsets, and stubs, whichever is presnt
*/
function buildFromDirectory(dirPath){
if(util.isExist(dirPath+"/dbsets")){
defaultConfig['dbsets'] = dirPath + '/dbsets/';
}

if(util.isExist(dirPath+"/stubs")){
defaultConfig['stubs'] = dirPath + '/stubs/';
}

if(util.isExist(dirPath+"/logs")){
defaultConfig['logs']['path'] = dirPath + '/logs/';
}else{
defaultConfig['logs']['path'] = dirPath + '/';
}

if(util.isExist(dirPath+"/dumps")){
defaultConfig['dumps'] = dirPath + '/dumps/';
}

var files = util.ls(dirPath+"/mappings");
if(files.length > 0){
defaultConfig['mappings']['requests'] = [];
files.forEach(function(filename){
defaultConfig['mappings']['requests'].push(dirPath + '/mappings/' + filename);
});
}
}

exports.getConfig= function(){
return defaultConfig;
}


3 changes: 1 addition & 2 deletions js/dbset.js
@@ -1,11 +1,10 @@
var HashTable = require('hashtable');
var preutil = require('./preutil');
var fs = require('fs'),
path = require('path');
var lineReader = require('line-reader');
var deasync = require('deasync');

var dirPath = preutil.getConfigFor('dbsets');
var dirPath = require("./configbuilder").getConfig().dbsets;
var dbsets = [];

if(dirPath){
Expand Down
15 changes: 6 additions & 9 deletions js/log.js
@@ -1,16 +1,13 @@
var winston = require('winston');
var util = require('./preutil');
var YAML = require('yamljs');
var config = require("./configbuilder").getConfig();

var logs = util.getConfigFor('logs');
var logs = config.logs.path || "";

var debuglogpath = "./debug.log"; //__dirname + debuglogpath
var errlogpath = "./exceptions.log";
var debuglogpath = logs + "/debug.log"; //__dirname + debuglogpath
var errlogpath = logs + "/exceptions.log";

console.log("writing logs to: " + debuglogpath +", "+ errlogpath);

if(logs){
debuglogpath = logs.info;
errlogpath = logs.error;
}
var logger = new (winston.Logger)({
transports: [
//new (winston.transports.Console)({ json: false, timestamp: true }),
Expand Down
25 changes: 13 additions & 12 deletions js/preutil.js
@@ -1,17 +1,18 @@
var YAML = require('yamljs');
var fs = require('fs');

var config;

try{
config = YAML.parseFile("./config.yaml");
}catch(e){
console.log("Config file is not found on root location of the project.");
exports.isExist = function(path){
try{
fs.accessSync(path, fs.F_OK);
return true;
}catch(e){
return false;
}
}

exports.getConfigFor = function(name){
for(var i in config){
if(config[i][name]){
return config[i][name];
}
/* Empty list if no file or directory not exist or access issues*/
exports.ls = function(dirpath){
if(exports.isExist(dirpath)){
return fs.readdirSync(dirpath);
}
return [];
}
39 changes: 11 additions & 28 deletions js/req_res_mappings.js
@@ -1,33 +1,15 @@
var YAML = require('yamljs');
var preutil = require('./preutil');
var config = require("./configbuilder").getConfig()

var config_mapping = preutil.getConfigFor('mappings');

if(!config_mapping){
config_mapping = {
//default: "./mappings/default.yaml" ,
requests: ["./response.yaml"]
}
}
var config_mapping = config.mappings;

var allMappings = [];

var defaultConfig;
if(config_mapping.default){
defaultConfig = YAML.parseFile(config_mapping.default);
}else{
defaultConfig = [{
response: {
status: 200,
latency: 0
}
}]
}

var defaultConfig = config_mapping.default;

for(var i in config_mapping.requests){
console.log("Loading mappings from " + config_mapping.requests[i]);
var mappings = YAML.parseFile(config_mapping.requests[i]);
console.log("Loading "+ mappings.length +" mappings from " + config_mapping.requests[i]);
if(!mappings || mappings.length == 0){
console.log(config_mapping.requests[i] + " is an empty file.");
break;
Expand All @@ -52,24 +34,24 @@ for(var i in config_mapping.requests){


if(!entry.response.status){
if(defaultConfig[0].response.status){
entry.response['status'] = defaultConfig[0].response.status;
if(defaultConfig.response.status){
entry.response['status'] = defaultConfig.response.status;
}else{
entry.response['status'] = 200;
}
}

if(!entry.response.latency){
if(defaultConfig[0].response.latency){
entry.response['latency'] = defaultConfig[0].response.latency;
if(defaultConfig.response.latency){
entry.response['latency'] = defaultConfig.response.latency;
}else{
entry.response['latency'] = 0;
}
}

if(!entry.response.strategy){
if(defaultConfig[0].response.strategy){
entry.response['strategy'] = defaultConfig[0].response.strategy;
if(defaultConfig.response.strategy){
entry.response['strategy'] = defaultConfig.response.strategy;
}else if(entry.response.files){
entry.response['strategy'] = 'not-found';
}
Expand All @@ -80,6 +62,7 @@ for(var i in config_mapping.requests){
}

}

allMappings = allMappings.concat(mappings);
}
exports.mappings = allMappings;

0 comments on commit dd8fcc9

Please sign in to comment.