1
Fork 0
This commit is contained in:
Conduitry 2018-07-06 22:21:18 -04:00
parent 4f98f7089a
commit 735bcd22d8
1 changed files with 28 additions and 30 deletions

58
shim.js
View File

@ -2,6 +2,9 @@ const EventEmitter = require('events');
const { watch } = require('fs'); const { watch } = require('fs');
const { request } = require('http'); const { request } = require('http');
const socketPath = '//./pipe/docker_engine';
const versionPrefix = '/v1.37';
// given a ClientRequest object, return a promise resolving to a Buffer of the entire response // given a ClientRequest object, return a promise resolving to a Buffer of the entire response
const response = request => const response = request =>
new Promise((resolve, reject) => new Promise((resolve, reject) =>
@ -19,39 +22,34 @@ const response = request =>
const api = async (method, endpoint, data) => { const api = async (method, endpoint, data) => {
const str = (await response( const str = (await response(
request({ request({
socketPath: '//./pipe/docker_engine', socketPath,
method, method,
path: '/v1.37' + endpoint, path: versionPrefix + endpoint,
headers: { 'content-type': 'application/json' }, headers: { 'content-type': 'application/json' },
}).end(data && JSON.stringify(data)), }).end(data && JSON.stringify(data)),
)).toString(); )).toString();
return str && JSON.parse(str); return str && JSON.parse(str);
}; };
// return event stream from Docker Engine API endpoint
const stream = endpoint => { const stream = endpoint => {
const emitter = new EventEmitter(); const emitter = new EventEmitter();
request( request({ socketPath, path: versionPrefix + endpoint }, response => {
{ let buffer = '';
socketPath: '//./pipe/docker_engine', response.on('data', data => {
path: '/v1.37' + endpoint, buffer += data.toString();
}, let p;
response => { while ((p = buffer.indexOf('\n')) !== -1) {
let buffer = ''; emitter.emit('', JSON.parse(buffer.slice(0, p)));
response.on('data', data => { buffer = buffer.slice(p + 1);
buffer += data.toString(); }
let p; });
while ((p = buffer.indexOf('\n')) !== -1) { }).end();
emitter.emit('', JSON.parse(buffer.slice(0, p)));
buffer = buffer.slice(p + 1);
}
});
},
).end();
return emitter; return emitter;
}; };
// handle a watch event // handle a watch event
const watchHandler = async (containerName, containerId, target, filename) => { const watchHandler = async (containerId, containerName, target, filename) => {
// determine the path inside the container // determine the path inside the container
const dest = target + '/' + filename.replace(/\\/g, '/'); const dest = target + '/' + filename.replace(/\\/g, '/');
console.log(`${containerName}: ${dest}`); console.log(`${containerName}: ${dest}`);
@ -66,7 +64,7 @@ const watchHandler = async (containerName, containerId, target, filename) => {
const watchers = new Map(); const watchers = new Map();
// attach a watcher for the given bind mount // attach a watcher for the given bind mount
const attachWatcher = (containerName, containerId, source, target) => { const attachWatcher = (containerId, containerName, source, target) => {
// debounce the fs.watch events and handle them // debounce the fs.watch events and handle them
const timeouts = new Map(); const timeouts = new Map();
console.log(`${containerName}: [watching] ${source} => ${target}`); console.log(`${containerName}: [watching] ${source} => ${target}`);
@ -77,8 +75,8 @@ const attachWatcher = (containerName, containerId, source, target) => {
setTimeout( setTimeout(
watchHandler, watchHandler,
10, 10,
containerName,
containerId, containerId,
containerName,
target, target,
filename, filename,
), ),
@ -98,8 +96,8 @@ const attachWatchers = async container => {
// determine the host path of the mount // determine the host path of the mount
arr.push( arr.push(
attachWatcher( attachWatcher(
info.Name ? info.Name.slice(1) : info.Id,
info.Id, info.Id,
info.Name ? info.Name.slice(1) : info.Id,
Source[10] + ':' + Source.slice(11).replace(/\//g, '\\'), Source[10] + ':' + Source.slice(11).replace(/\//g, '\\'),
Destination, Destination,
), ),
@ -109,7 +107,7 @@ const attachWatchers = async container => {
}; };
// detach all watchers for a given container // detach all watchers for a given container
const detachWatchers = (containerName, containerId) => { const detachWatchers = (containerId, containerName) => {
console.log(`${containerName}: [closing]`); console.log(`${containerName}: [closing]`);
for (const watcher of watchers.get(containerId)) { for (const watcher of watchers.get(containerId)) {
watcher.close(); watcher.close();
@ -128,14 +126,14 @@ const detachWatchers = (containerName, containerId) => {
stream( stream(
'/events?filters=%7B%22type%22%3A%5B%22container%22%5D%2C%22event%22%3A%5B%22start%22%2C%22die%22%5D%7D', '/events?filters=%7B%22type%22%3A%5B%22container%22%5D%2C%22event%22%3A%5B%22start%22%2C%22die%22%5D%7D',
).on('', event => { ).on('', event => {
const container =
event.Actor && event.Actor.Attributes && event.Actor.Attributes.name
? event.Actor.Attributes.name
: event.id;
if (event.Action === 'start') { if (event.Action === 'start') {
attachWatchers(container, event.id); attachWatchers(event.id);
} else if (event.Action === 'die') { } else if (event.Action === 'die') {
detachWatchers(container, event.id); const containerName =
event.Actor && event.Actor.Attributes && event.Actor.Attributes.name
? event.Actor.Attributes.name
: event.id;
detachWatchers(event.id, containerName);
} }
}); });
for (const container of await api('get', '/containers/json')) { for (const container of await api('get', '/containers/json')) {