cluster-service
Advanced tools
Comparing version 0.8.0 to 0.9.0
@@ -12,6 +12,6 @@ var util = require("util"), | ||
cservice.log("Exiting now.".warn); | ||
process.exit(0); // exit master | ||
cb(null, "Exiting now."); | ||
setTimeout(function() { | ||
process.exit(0); // exit master | ||
}, 100); | ||
}; | ||
@@ -18,0 +18,0 @@ |
@@ -39,2 +39,6 @@ var util = require("util"); | ||
}); | ||
}; | ||
}; | ||
module.exports.control = function() { | ||
return "local"; | ||
}; |
@@ -45,12 +45,31 @@ var async = require("async"), | ||
return function(cb) { | ||
worker.once("message", function(msg) { | ||
if (!msg || !msg.processDetails) { | ||
cb("processDetails not returned"); | ||
return; // end | ||
var timer, msgCb, processDetails, netStats; | ||
msgCb = function (msg) { | ||
if (msg && msg.processDetails) { | ||
processDetails = msg.processDetails; | ||
} | ||
worker.processDetails = msg.processDetails; | ||
cb(null, worker); | ||
}); | ||
// todo! timeout needed? perhaps. | ||
if (msg && msg.netStats) { | ||
netStats = msg.netStats; | ||
} | ||
if (processDetails && netStats) { | ||
clearTimeout(timer); | ||
worker.removeListener("message", msgCb); | ||
worker.processDetails = processDetails; | ||
processDetails.net = netStats; | ||
cb(null, worker); | ||
} | ||
}; | ||
timer = setTimeout(function() { | ||
worker.removeListener("message", msgCb); | ||
if (processDetails) { // net stats not required for success | ||
worker.processDetails = processDetails; | ||
cb(null, worker); | ||
} else { | ||
cb("getProcessDetails TIMEOUT"); | ||
} | ||
}, 1000); | ||
worker.on("message", msgCb); | ||
worker.process.send({cservice: "processDetails"}); | ||
worker.process.send({cservice: "netStats"}); | ||
}; | ||
@@ -57,0 +76,0 @@ } |
var _controls = {}; | ||
var _keys = {}; | ||
@@ -26,8 +27,72 @@ var levels = { | ||
function authorize(name, control) { | ||
function setAccessKey(keys) { | ||
_keys = {}; | ||
var keyArr = keys.split(";"); | ||
for (var i = 0; i < keyArr.length; i++) { | ||
var fullKey = keyArr[i]; | ||
var keyName = /([a-zA-Z0-9]*)?/.exec(fullKey)[0]; | ||
var keyDisabled = /[a-zA-Z0-9]*\:disabled/.test(fullKey); | ||
if (keyDisabled === true) { | ||
_keys[keyName] = false; | ||
continue; | ||
} | ||
var key = { }; | ||
var cmdList = /\[(.*)?\]/.exec(fullKey); | ||
if (cmdList && cmdList.length > 0) { | ||
var cmds = cmdList[1].split(","); | ||
for (var i2 = 0; i2 < cmds.length; i2++ ){ | ||
var fullCmd = cmds[i2]; | ||
var cmdName = /([a-zA-Z0-9]*)?/.exec(fullCmd)[0]; | ||
var cmdValStr = /\:(.*)?/.exec(fullCmd); | ||
var cmdVal = true; | ||
if (cmdValStr && cmdValStr.length > 0) { | ||
switch (cmdValStr[1]) { | ||
case "false": | ||
case "disabled": | ||
cmdVal = "disabled"; | ||
break; | ||
case "remote": | ||
cmdVal = "remote"; | ||
break; | ||
case "local": | ||
cmdVal = "local"; | ||
break; | ||
case "inproc": | ||
cmdVal = "inproc"; | ||
break; | ||
} | ||
key[cmdName] = cmdVal; | ||
} | ||
} | ||
} | ||
_keys[keyName] = key; | ||
} | ||
} | ||
function authorize(name, currentControl, accessKey) { | ||
if (typeof accessKey === "string" && accessKey in _keys) { | ||
// if access key available, check rights | ||
var rights = _keys[accessKey]; | ||
if (rights === false) { | ||
return false; // DENIED | ||
} else if (typeof rights === "object" && name in rights) { | ||
// custom rights detected | ||
var commandRight = rights[name]; | ||
if (typeof commandRight === "boolean") { | ||
return commandRight; // return as is | ||
} else if (typeof commandRight === "string" && commandRight in levels) { | ||
return currentControl >= levels[commandRight]; | ||
} | ||
} | ||
} | ||
if (_controls[name]) { | ||
return control >= _controls[name]; | ||
return currentControl >= _controls[name]; | ||
} | ||
// We default to "remote" which is full access | ||
return control >= levels.remote; | ||
return currentControl >= levels.remote; | ||
} | ||
@@ -37,3 +102,4 @@ | ||
exports.addControls = addControls; | ||
exports.setAccessKey = setAccessKey; | ||
exports.authorize = authorize; | ||
exports.levels = levels; |
@@ -22,3 +22,2 @@ var cservice = require("../cluster-service"), | ||
server.on("error", cb); | ||
server.listen(options.port, options.host, cb); | ||
@@ -62,5 +61,12 @@ }; | ||
} | ||
question = qs.cmd || "?"; | ||
onCommand(req, res, question); | ||
question = qs.cmd || ""; | ||
req.on('data', function (chunk) { | ||
question += chunk; | ||
}); | ||
req.on('end', function () { | ||
onCommand(req, res, question, qs.accessKey); | ||
}); | ||
} catch (ex) { | ||
@@ -75,3 +81,3 @@ cservice.error( | ||
function onCommand(req, res, question) { | ||
function onCommand(req, res, question, accessKey) { | ||
var args = require("./util").getArgsFromQuestion(question, " "); | ||
@@ -97,3 +103,3 @@ var controlLevel; | ||
isAuthorized = control.authorize(args[0], controlLevel); | ||
isAuthorized = control.authorize(args[0], controlLevel, accessKey); | ||
@@ -100,0 +106,0 @@ if (!isAuthorized) { |
@@ -147,4 +147,6 @@ /* jshint loopfunc:true */ | ||
return; | ||
} else { | ||
require("./control").setAccessKey(options.accessKey); | ||
} | ||
httpserver.init(cservice.locals, options, function(err) { | ||
@@ -151,0 +153,0 @@ if (!err) { |
@@ -5,3 +5,10 @@ var cservice = require("../cluster-service"); | ||
var monitoring = false; | ||
function netStats(server) { | ||
if (monitoring === false) { | ||
monitoring = true; | ||
monitor(); // init monitor | ||
} | ||
server.on("connection", function(connection) { | ||
@@ -19,1 +26,23 @@ cservice.locals.stats.net.connections++; | ||
} | ||
// Why in its own monitor? Worker may reference different version of cservice | ||
// than the master, which is where these stats are tracked (to avoid blasting | ||
// messages when the data is not needed). | ||
// TODO: Move worker stats to its own class so this technique can be leveraged | ||
// for any type of stats in the future. | ||
function monitor() { | ||
process.on("message", function(msg) { | ||
if (!msg || typeof msg.cservice !== "string") { | ||
return; // ignore | ||
} | ||
switch (msg.cservice) { | ||
case "netStats": | ||
process.send({ | ||
cservice: "netStats", | ||
netStats: cservice.locals.stats.net | ||
}); | ||
break; | ||
} | ||
}); | ||
} |
@@ -7,5 +7,3 @@ var cservice = require("../cluster-service"); | ||
if (cservice.locals.state === 0) { | ||
if(cb){ | ||
cb(); | ||
} | ||
if (cb) cb(null, "Not running"); | ||
return; | ||
@@ -16,12 +14,10 @@ } | ||
cservice.trigger("shutdown", function() { | ||
if (cb) cb(null, "Shutting down..."); | ||
require("./http-server").close(); | ||
if (cservice.options.cli === true) { | ||
process.exit(1); | ||
} else { | ||
if(cb){ | ||
cb(); | ||
} | ||
} | ||
}, "all", timeout); | ||
} else { // gracefully shutdown | ||
if (cb) cb(null, "Shutting down..."); | ||
require("./http-server").close(); | ||
@@ -31,8 +27,4 @@ cservice.locals.state = 0; | ||
process.exit(1); | ||
} else { | ||
if(cb){ | ||
cb(); | ||
} | ||
} | ||
} | ||
} |
The MIT License (MIT) | ||
Copyright (c) 2013 Go Daddy | ||
Copyright (c) 2014 GoDaddy | ||
@@ -21,2 +21,2 @@ Permission is hereby granted, free of charge, to any person obtaining a copy | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
THE SOFTWARE. |
{ | ||
"name": "cluster-service", | ||
"version": "0.8.0", | ||
"version": "0.9.0", | ||
"author": { | ||
@@ -5,0 +5,0 @@ "name": "Aaron Silvas", |
@@ -307,9 +307,9 @@ # cluster-service | ||
var server = require("http").createServer(onRequest); | ||
require("cluster-service").netStats(server); // listen to net stats | ||
var server = require("http").createServer(onRequest); | ||
require("cluster-service").netStats(server); // listen to net stats | ||
Or you can provide the net server objects via the ```servers``` option: | ||
var server = require("http").createServer(onRequest); | ||
require("cluster-service").workerReady({ servers: [server] }); // listen to net stats | ||
var server = require("http").createServer(onRequest); | ||
require("cluster-service").workerReady({ servers: [server] }); // listen to net stats | ||
@@ -338,5 +338,10 @@ Net statistics summary may be found via the ```info``` command, and individual process | ||
## Change Log | ||
[Change Log](https://github.com/godaddy/node-cluster-service/blob/master/CHANGELOG.md) | ||
## License | ||
[MIT](https://github.com/godaddy/node-cluster-service/blob/master/LICENSE.txt) |
@@ -109,2 +109,48 @@ var control = require("../lib/control"); | ||
}); | ||
describe('authorize keys', function() { | ||
it('key not found, access NOT granted', function(done) { | ||
control.setControls({ "test": "local"}); | ||
control.setAccessKey("abc"); | ||
var isAuthorized = control.authorize("test", control.levels.remote, "X"); | ||
assert.equal(isAuthorized, false, "isAuthorized should be false."); | ||
done(); | ||
}); | ||
it('key not found, access IS granted', function(done) { | ||
control.setControls({ "test": "local"}); | ||
control.setAccessKey("abc"); | ||
var isAuthorized = control.authorize("test", control.levels.local, "X"); | ||
assert.equal(isAuthorized, true, "isAuthorized should be true."); | ||
done(); | ||
}); | ||
it('key found, access NOT granted', function(done) { | ||
control.setControls({ "test": "local"}); | ||
control.setAccessKey("abc:disabled"); | ||
var isAuthorized = control.authorize("test", control.levels.local, "abc"); | ||
assert.equal(isAuthorized, false, "isAuthorized should be false."); | ||
done(); | ||
}); | ||
it('key found, access IS granted', function(done) { | ||
control.setControls({ "test": "local"}); | ||
control.setAccessKey("abc"); | ||
var isAuthorized = control.authorize("test", control.levels.local, "abc"); | ||
assert.equal(isAuthorized, true, "isAuthorized should be true."); | ||
done(); | ||
}); | ||
it('key found, specials rights PREVENT access', function(done) { | ||
control.setControls({ "test": "local"}); | ||
control.setAccessKey("abc[test:inproc]"); | ||
var isAuthorized = control.authorize("test", control.levels.local, "abc"); | ||
assert.equal(isAuthorized, false, "isAuthorized should be false."); | ||
done(); | ||
}); | ||
it('key found, specials rights ALLOW access', function(done) { | ||
control.setControls({ "test": "local"}); | ||
control.setAccessKey("abc[test:remote]"); | ||
var isAuthorized = | ||
control.authorize("test", control.levels.remote, "abc"); | ||
assert.equal(isAuthorized, true, "isAuthorized should be true."); | ||
done(); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
118891
67
3097
346