Created
July 16, 2014 21:03
-
-
Save sadasant/9cd0a66b26ee5600d7df to your computer and use it in GitHub Desktop.
Simple etcd client with tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var request = require("request"); | |
var qstr = require("querystring").stringify; | |
var Args = require("args-js"); | |
var utils = require("../utils"); | |
var etcd = module.exports = {}; | |
var watchers = etcd.watchers = {}; | |
var timeout_code = "ESOCKETTIMEDOUT"; | |
etcd.host = process.env.ETCDHOST || "127.0.0.1"; | |
etcd.port = process.env.ETCDPORT || "4001"; | |
etcd.protocol = "http"; | |
etcd.getURL = function(key, params) { | |
for (var k in params) { | |
if (params[k] === undefined) delete params[k]; | |
} | |
return this.protocol + "://" + this.host + ":" + this.port + "/v2/keys/" + key + (params ? "?" + qstr(params) : ""); | |
}; | |
etcd.watch = function() { | |
var args = Args([ | |
{key: Args.STRING | Args.Required}, | |
{done: Args.FUNCTION | Args.Required} | |
], arguments); | |
var url = etcd.getURL(args.key, { | |
wait: true | |
}); | |
watchers[args.key] = watcher; | |
watcher(); | |
function watcher() { | |
if (!watchers[args.key]) return; | |
request.get(url, function(error, res, body) { | |
if (error && error.code === timeout_code) return watcher(); | |
args.done(utils.parseJSON(body)); | |
watcher(); | |
}); | |
} | |
}; | |
etcd.unwatch = function(key) { | |
watchers[key] = undefined; | |
}; | |
etcd.set = function() { | |
var original_arguments = arguments; | |
var args = Args([ | |
{key: Args.STRING | Args.Required}, | |
[ | |
{value: Args.STRING | Args.Required}, | |
{value: Args.OBJECT | Args.Required}, | |
], | |
{prevValue: Args.STRING | Args.Optional}, | |
{prevExist: Args.BOOL | Args.Optional}, | |
{done: Args.FUNCTION | Args.Optional} | |
], arguments); | |
if (typeof args.value === "object") { | |
args.value = JSON.stringify(args.value); | |
} | |
request.put(etcd.getURL(args.key, { | |
value: args.value, | |
prevValue: args.prevValue, | |
prevExist: args.prevExist | |
}), function(error, res, body) { | |
if (error && error.code === timeout_code) return etcd.set.apply(etcd, original_arguments); | |
if (args.done) args.done(utils.parseJSON(body)); | |
}); | |
}; | |
etcd.get = function() { | |
var original_arguments = arguments; | |
var args = Args([ | |
{key: Args.STRING | Args.Required}, | |
{done: Args.FUNCTION | Args.Required} | |
], arguments); | |
request.get(etcd.getURL(args.key), function(error, res, body) { | |
if (error && error.code === timeout_code) return etcd.get.apply(etcd, original_arguments); | |
args.done(utils.parseJSON(body)); | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var etcd = require("./etcd"); | |
var assert = require("assert"); | |
var tests = []; | |
tests.push(function(done) { | |
console.log("\nCASE1: watch and set"); | |
etcd.watch("hello", function(data) { | |
assert.equal(data.node.value, "world!"); | |
done(); | |
}); | |
etcd.set("hello", "world!"); | |
etcd.unwatch("hello"); | |
}); | |
tests.push(function(done) { | |
console.log("\nCASE2: compareAndSwap checkSwap"); | |
// As in https://github.com/coreos/etcd/blob/master/Documentation/api.md#atomic-compare-and-swap | |
// Here is a simple example. Let's create a key-value pair first: `hello=one`. | |
etcd.set("hello", "one"); | |
// Trying to set this existing key with prevExist=false fails as expected: | |
etcd.set("hello", "three", false, function(data) { | |
// The error code explains the problem: | |
assert.equal(data.errorCode, 105); | |
assert.equal(data.message, "Key already exists"); | |
// Now let's provide a prevValue parameter: | |
etcd.set("hello", "three", "two", function(data) { | |
assert.equal(data.errorCode, 101); | |
assert.equal(data.cause, "[two != one]"); | |
// which means CompareAndSwap failed. cause explains why the test failed. Note: the condition prevIndex=0 always passes. | |
// Let's try a valid condition: | |
etcd.set("hello", "two", "one", function(data) { | |
assert.equal(data.node.value, "two"); | |
assert.equal(data.prevNode.value, "one"); | |
done(); | |
}); | |
}); | |
}); | |
}); | |
tests.push(function(done) { | |
console.log("\nCASE3: etcd.get"); | |
// Here is a simple example. Let's create a key-value pair first: `hello=one`. | |
etcd.get("hello", function(data) { | |
// console.log(data); | |
assert.equal(data.node.value, "two"); | |
done(); | |
}); | |
}); | |
function callNext() { | |
var test = tests.shift(); | |
if (test) { | |
test(function() { | |
console.log("DONE!"); | |
callNext(); | |
}); | |
} | |
} | |
callNext(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment