require('require-yaml'); let Docker = require('dockerode'); let handlebars = require('handlebars'); let ssh = require('node-ssh'); let fs = require('fs'); let conf = require('./config.yml'); let docker; let template; let isProduction = process.env.NODE_ENV === 'production'; async function updateProxy() { console.log('Updating reverse proxy configuration.'); let info; if (!isProduction) { info = require('./test.json'); } else { info = { services: await docker.listServices(), nodes: await docker.listNodes() }; } let services = []; for (let serviceInfo of info.services) { let ports = serviceInfo.Endpoint.Ports; if (!Array.isArray(ports) || !ports.length) continue; let name = serviceInfo.Spec.Name; let match = name.match(/(.+)_main$/); if (match) name = match[1]; let service = { name, port: ports[0].PublishedPort, nodes: [] }; services.push(service); for (let node of info.nodes) { let address = node.ManagerStatus ? node.ManagerStatus.Addr.split(':')[0] : node.Status.Addr; service.nodes.push({ name: node.Description.Hostname, endpoint: `${address}:${service.port}` }); } } let tmpConf = `/tmp/rproxy.${new Date().getTime()}`; let configString = template({info, services}); fs.writeFileSync(tmpConf, configString); if (conf.debug || !isProduction) { let delimiter = '#'.repeat(80); console.log(delimiter); console.log(configString); console.log(delimiter); } let files = { local: tmpConf, remote: conf.rproxy.confPath }; for (let host of conf.rproxy.hosts) { console.log(`Updating host: ${host}`); if (!isProduction) continue; let sshClient = new ssh(); await sshClient.connect(Object.assign({host}, conf.rproxy.auth)); await sshClient.putFiles([files]); if (conf.rproxy.reloadCmd) await sshClient.exec(conf.rproxy.reloadCmd); await sshClient.dispose(); } fs.unlinkSync(tmpConf); console.log('Configuration updated.'); } (async() => { let timeoutId; docker = new Docker(conf.docker); template = handlebars.compile(fs.readFileSync('rproxy.handlebars', 'utf8')); await updateProxy(); console.log('Listenig for events.') docker.getEvents({}, (err, stream) => { if (err || !stream) { console.error('Failed to monitor docker host', err); return; } stream.on('data', event => { event = JSON.parse(event); if (conf.events && conf.events.indexOf(event.Type) == -1) return; console.log(`Event: ${event.Type}: ${event.Action}`); if (timeoutId) return; timeoutId = setTimeout(async () => { timeoutId = null; await updateProxy(); }, conf.delay * 1000); }) }); })();