This repository has been archived on 2024-07-12. You can view files and clone it, but cannot push or open issues or pull requests.
docker-discover/index.js

151 lines
4.0 KiB
JavaScript
Raw Normal View History

2020-01-28 13:57:24 +00:00
require('require-yaml');
2020-01-27 16:25:39 +00:00
let Docker = require('dockerode');
let handlebars = require('handlebars');
let ssh = require('node-ssh');
let fs = require('fs');
let shajs = require('sha.js');
2020-01-28 13:57:24 +00:00
let conf = require('./config.yml');
let package = require('./package.json');
2020-01-27 16:25:39 +00:00
let docker;
let template;
let lastInfoHash;
let appName = package.name;
2020-01-28 13:57:24 +00:00
let isProduction = process.env.NODE_ENV === 'production';
let tmpDir = isProduction ? `/tmp/${appName}` : `${__dirname}/tmp`;
let hashFile = `${tmpDir}/config.hash`;
2020-01-27 16:25:39 +00:00
async function updateProxy() {
2020-01-28 13:57:24 +00:00
console.log('Updating reverse proxy configuration.');
// Obtaining Docker settings
2020-01-28 13:57:24 +00:00
let info;
2020-01-27 16:25:39 +00:00
2020-01-28 13:57:24 +00:00
if (!isProduction) {
info = require('./test.json');
2020-01-27 16:25:39 +00:00
} else {
2020-01-28 13:57:24 +00:00
info = {
2020-01-27 16:25:39 +00:00
services: await docker.listServices(),
nodes: await docker.listNodes()
};
}
2020-01-28 13:57:24 +00:00
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$/);
2020-01-28 13:57:24 +00:00
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}`
});
}
}
// Cheking settings hash
let infoHash = shajs('sha256')
.update(JSON.stringify(services))
.digest('hex');
console.log('Settings hash:', infoHash);
if (lastInfoHash == infoHash) {
console.log(`Settings haven't changed, aborting.`);
return;
}
lastInfoHash = infoHash;
fs.writeFileSync(hashFile, infoHash);
// Creating configuration file
let tmpConf = `${tmpDir}/config.cfg`;
2020-01-28 13:57:24 +00:00
let configString = template({info, services});
2020-01-27 16:25:39 +00:00
fs.writeFileSync(tmpConf, configString);
if (conf.debug) {
2020-01-27 16:25:39 +00:00
let delimiter = '#'.repeat(80);
console.log(delimiter);
console.log(configString);
console.log(delimiter);
}
// Updating reverse proxies
2020-01-27 16:25:39 +00:00
let files = {
local: tmpConf,
2020-01-28 13:57:24 +00:00
remote: conf.rproxy.confPath
2020-01-27 16:25:39 +00:00
};
2020-01-28 13:57:24 +00:00
for (let host of conf.rproxy.hosts) {
2020-01-27 16:25:39 +00:00
console.log(`Updating host: ${host}`);
2020-01-28 13:57:24 +00:00
if (!isProduction) continue;
2020-01-27 16:25:39 +00:00
let sshClient = new ssh();
2020-01-28 13:57:24 +00:00
await sshClient.connect(Object.assign({host}, conf.rproxy.auth));
2020-01-27 16:25:39 +00:00
await sshClient.putFiles([files]);
2020-01-28 13:57:24 +00:00
if (conf.rproxy.reloadCmd)
2020-01-28 15:43:43 +00:00
await sshClient.exec(conf.rproxy.reloadCmd);
2020-01-27 16:25:39 +00:00
await sshClient.dispose();
}
console.log('Configuration updated.');
}
(async() => {
console.log('Initializing.');
2020-01-27 16:25:39 +00:00
let timeoutId;
docker = new Docker(conf.docker);
template = handlebars.compile(fs.readFileSync('rproxy.handlebars', 'utf8'));
try {
fs.mkdirSync(tmpDir);
} catch (err) {
if (err.code != 'EEXIST') throw err;
}
if (fs.existsSync(hashFile)) {
lastInfoHash = fs.readFileSync(hashFile, 'utf8');
console.log('Saved settings hash:', lastInfoHash);
}
2020-01-28 13:57:24 +00:00
await updateProxy();
2020-01-27 16:25:39 +00:00
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;
2020-01-28 13:57:24 +00:00
timeoutId = setTimeout(async () => {
2020-01-27 16:25:39 +00:00
timeoutId = null;
2020-01-28 13:57:24 +00:00
await updateProxy();
2020-01-27 16:25:39 +00:00
}, conf.delay * 1000);
})
});
})();