Skip to content

Commit

Permalink
Added console command to sync kv config with consul
Browse files Browse the repository at this point in the history
  • Loading branch information
jessehansen committed Nov 9, 2015
1 parent 9a7866b commit 600d4a1
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 2 deletions.
25 changes: 25 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"rules": {
"indent": [
2,
2,
{"SwitchCase": 1}
],
"quotes": [
2,
"single"
],
"linebreak-style": [
2,
"unix"
],
"semi": [
2,
"always"
]
},
"env": {
"node": true
},
"extends": "eslint:recommended"
}
68 changes: 68 additions & 0 deletions consul-kv-sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env node

var fs = require('fs');
var Promise = require('bluebird');
var program = require('commander');
var jptr = require('json-ptr');
var _ = require('lodash');
var request = require('request-promise');
var base64 = require('js-base64').Base64;

var pkg = require('./package.json');

var readFile = Promise.promisify(fs.readFile);

function readFragments(fileName) {
return readFile(fileName, "utf8").then(function(contents){
return jptr.list(JSON.parse(contents));
});
}

request.defaults({json:true});

program.version(pkg.version)
.description("Synchronizes one or more JSON manifests with consul's key value store")
.option('-H, --host <host>', "Consul API url, default: http://consul.service.consul:8500");

program.parse(process.argv);

var host = program.host || process.env.CONSUL_HOST || 'http://consul.service.consul:8500/';

Promise.all(_.map(program.args, readFragments)).then(function (files){
var flattened = _.flatten(files);
var prefix = flattened[1].fragmentId.substring(2);
var reduced = _.reduce(_.filter(flattened, function(x){ return _.isString(x.value) || _.isFinite(x.value)}), function(acc, item){
acc[item.fragmentId.substring(2)] = item.value;
return acc;
}, {});

var existing = {};
request.get(host + 'v1/kv/' + prefix + '?recurse=1', {json: true})
.then(function (res) {
_.each(res, function(item){
existing[item.Key] = base64.decode(item.Value);
})
if (res.statusCode == 200) {
existing = res.body;
}
return;
}).catch(function(err){
console.log(err);
//ignore errors, jus
}).then(function(){
return Promise.all(_.map(reduced, function(value, key){
delete existing[key];
return request.put(host + 'v1/kv/' + key, {body:''+value});
}));
}).then(function(){
return Promise.all(_.map(existing, function(value, key){
return request(host + 'v1/kv/' + key, {method:'DELETE'});
}));
}).then(function(){
console.log(reduced);
console.log('Synced');
});
});

if (!program.args.length) program.help();

14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,21 @@
}
],
"scripts": {
"test": "mocha test"
"test": "mocha",
"test:watch": "onchange 'test/**/*' '*.js' '*.json' -- npm run test",
"lint": "esw --quiet",
"lint:watch": "esw --quiet --watch",
"ci": "npm run lint && npm run test"
},
"dependencies": {
"assert-plus": "^0.1.5",
"bluebird": "^3.0.5",
"commander": "^2.9.0",
"js-base64": "^2.1.9",
"json-ptr": "^0.2.0",
"lodash": "^3.10.1",
"request": "^2.65.0"
"request": "^2.65.0",
"request-promise": "^1.0.2"
},
"config": {
"title": "Consul KV Sync",
Expand All @@ -35,6 +43,8 @@
},
"devDependencies": {
"chai": "^3.3.0",
"eslint": "^1.9.0",
"eslint-watch": "^2.1.3",
"istanbul": "^0.4.0",
"mocha": "^2.2.5",
"onchange": "^2.0.0"
Expand Down
6 changes: 6 additions & 0 deletions test/one.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"service": {
"one": "value 1",
"two": "value 2"
}
}
70 changes: 70 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@

var exec = require('child_process').exec;
var expect = require('chai').expect;
var request = require('request-promise');
var base64 = require('js-base64').Base64;
var _ = require('lodash');

var host = process.env.CONSUL_HOST || 'http://consul.service.consul:8500/';

describe('consul-kv-sync', function(){

describe('#run', function(){
var response;
before(function(done){
request.put(host + 'v1/kv/service/four', {
body: 'value for removal',
json: true
}).then(function(){

var proc = exec('node ../consul-kv-sync.js --host "' + host + '" ./one.json ./two.json', {cwd:__dirname});
proc.on('exit', function(){
request.get(host + 'v1/kv/service?recurse=1', {json: true}).then(function(result){
response = result;
done();
}).catch(done);
});
});
});

it ('should set value to correct value', function(){
var item = response.find(function(item){
return item.Key == 'service/two';
});

expect(item).to.be.ok;
expect(base64.decode(item.Value)).to.eql('value 2');
});

it ('should set overridden value to correct value', function(){
var item = response.find(function(item){
return item.Key == 'service/one';
});

expect(item).to.be.ok;
expect(base64.decode(item.Value)).to.eql('value from file two');
});

it ('should set array parameters correctly', function(){
var items = _.filter(response, function(item){
return /^service\/arrayparam/.test(item.Key);
});

expect(items.length).to.eql(4);
expect(items[0].Key).to.eql('service/arrayparam/0');
expect(base64.decode(items[0].Value)).to.eql('1');
expect(base64.decode(items[1].Value)).to.eql('2');
expect(base64.decode(items[2].Value)).to.eql('3');
expect(base64.decode(items[3].Value)).to.eql('4');
});

it ('should set remove existing keys that are not in config file', function(){
var items = _.filter(response, function(item){
return item.Key == 'service/four';
});

expect(items.length).to.eql(0);
});

});
});
7 changes: 7 additions & 0 deletions test/two.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"service": {
"one": "value from file two",
"three": "value 3",
"arrayparam": [1,2,3,4]
}
}

0 comments on commit 600d4a1

Please sign in to comment.