Created
October 10, 2013 08:26
-
-
Save tjfontaine/6914917 to your computer and use it in GitHub Desktop.
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 execFile = require('child_process').execFile; | |
var EE = require('events').EventEmitter; | |
var util = require('util'); | |
var vm = require('vm'); | |
module.exports = Charm; | |
function Charm(options) { | |
if (!(this instanceof Charm)) return new Charm(options); | |
// delay a tick so things can attach, maybe have a separate init that users pass in instead of this being magic on first require | |
var self = this; | |
process.nextTick(function() { | |
//argv[0] is node, argv[1] is script name, the rest will be args for the hook | |
var hook = process.argv[1]; | |
//if we have defined a prototype method for this call it instead. otherwise re-emit | |
if (self[hook]) | |
self[hook].apply(self, process.argv.slice(2)); | |
else | |
self.emit.apply(self, process.argv.slice(1)); | |
}); | |
// assuming charm.js is in lib/charm.js the config file defaults to config/config.js | |
this.CONFIG_FILE = options.config || path.join(__dirname, '..', 'config', 'config.js'); | |
} | |
util.inherits(Charm, EE); | |
Charm.prototype.relation_get = function(key, cb) { | |
this.exec('relation-get', [key], cb); | |
}; | |
// should be a dict I guess? | |
Charm.prototype.relation_set = function(key, value, cb) { | |
this.exec('relation-set', [key, value], cb); | |
}; | |
Charm.prototype.log = function(msg, cb) { | |
this.exec('juju-log', [msg], cb); | |
}; | |
/* evil this exits like set -e does */ | |
Charm.prototype.exec = function(cmd, args, cb) { | |
execFile(cmd, args, function(err, stderr, stdout) { | |
if (err) { | |
self.log(util.format('failed to run: %s %j %j', cmd, args, err)); | |
process.exit(1); | |
return; | |
} | |
cb(stdout ? stdout.trim() : ''); | |
}); | |
}; | |
Charm.prototype.configUpdate = function(section, value, cb) { | |
var self = this; | |
fs.readFile(this.CONFIG_FILE, 'utf8', function(err, value) { | |
// todo err handling -- like file creation? | |
var config = vm.runInNewContext('(function(){ return ' + value + ' })()'); | |
var s = config[section] || {}; | |
util._extend(s, value); | |
config[section] = s; | |
}); | |
}; | |
Charm.prototype['database-relation-changed'] = function() { | |
var self = this; | |
// use control flow mechanism to avoid callback hell | |
// preferably vasync | |
self.relation_get('user', function(user) { | |
self.relation_get('db', function(db) { | |
self.relation_get('pass', function(pass) { | |
self.relation_get('private-address', function(addr) { | |
self.emit('database-relation-changed', user, db, pass, addr); | |
}); | |
}); | |
}); | |
}); | |
}; |
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
{ | |
'database': { | |
}, | |
} |
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
#!/usr/bin/env node | |
var charm = require('charm')(); | |
charm.on('database-relation-changed', function(user, db, pass, addr) { | |
charm.configUpdate('database', { | |
user: user, | |
db: db, | |
pass: pass, | |
addr: addr, | |
}, function() { | |
// config successfully updated | |
}); | |
}); |
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
#!/usr/bin/env node | |
var charm = require('charm')(); | |
charm.on('start', function() { | |
charm.exec('service', ['node-app', 'start'], function(ret) { | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can fetch all the params for a relation in a single relation-get call. you should also test conditionally those values have been set, and exit otherwise, the other side may not have had a chance to set values on the relation yet when the hook executes. juju guarantees the execution of relation-changed again when the remote settings are updated.