module.exports = function() { var module={}; module.connection = function(socket) { //var sys = require('sys'); var pty = require('pty.js'); var proc = require('child_process'); console.log("new client"); function emit(signal, data, info) { if (typeof data == 'string' && !data.match("\n")) { console.log("<- signal: "+signal+"("+data+")"); } else { console.log("<- signal: "+signal); } if (info) console.log(info); socket.emit(signal, data); } function broadcast(signal, data) { console.log("<= signal: "+signal); socket.broadcast.emit(signal, data); } function exec(cmd, callback) { console.log("== "+cmd); proc.exec(cmd, callback); } function fail(txt, data) { console.log("** "+txt, data); emit("fail", txt); } function containerinspect(error, stdout, stderr) { if (error || stderr) return fail("inspect docker containers failed", { error: error, stderr: stderr, stdout: stdout }); emit("containers", stdout); } function containerlist(error, stdout, stderr) { if (error || stderr) return fail("list docker containers failed", { error: error, stderr: stderr, stdout: stdout }); exec("docker inspect "+stdout.trim().replace(/\n/g, " "), containerinspect); } function updatecontainers(error, stdout, stderr) { if (error || stderr) return fail("update docker container failed", { error: error, stderr: stderr, stdout: stdout }); exec("docker ps -aq", containerlist); } function modify(cmd, name) { if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i)) return fail("illegal instance name"); exec("docker "+cmd+" "+name, updatecontainers); } function containers() { console.log("-> containers"); updatecontainers(); } function imageinspect(error, stdout, stderr) { if (error || stderr) return fail("inspect docker images failed", { error: error, stderr: stderr, stdout: stdout }); emit("images", stdout); } function imagelist(error, stdout, stderr) { if (error || stderr) return fail("list docker images failed", { error: error, stderr: stderr, stdout: stdout }); exec("docker inspect "+stdout.trim().replace(/\n/g, " "), imageinspect); } function updateimages(error, stdout, stderr) { if (error || stderr) return fail("update docker images failed", { error: error, stderr: stderr, stdout: stdout }); exec("docker images -q", imagelist); } function modify(cmd, name) { if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i)) return fail("illegal instance name"); exec("docker "+cmd+" "+name, updatecontainers); } function containers() { console.log("-> containers"); updatecontainers(); } function images() { console.log("-> images"); updateimages(); } function start(name) { console.log("-> start("+name+")"); modify("start", name); } function stop(name) { console.log("-> stop("+name+")"); modify("stop", name); } function pause(name) { console.log("-> pause("+name+")"); modify("pause", name); } function unpause(name) { console.log("-> unpause("+name+")"); modify("unpause", name); } function remove(name) { console.log("-> remove("+name+")"); modify("rm", name); } function logs(name) { console.log("-> logs("+name+")"); var l = proc.spawn("docker", ["logs", "-f", name]) .on('close', function(code) { emit('logs', {name: name, type: 'done'}); }); l.stdout.on('data', function(data) { emit('logs', {name: name, type: 'stdout', text: data.toString()}); }); l.stderr.on('data', function(data) { emit('logs', {name: name, type: 'stderr', text: data.toString()}); }); } var bash_connections = {}; function new_bash(name) { if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i)) return fail("illegal instance name"); if (bash_connections[name]) return; bash_connections[name] = pty.spawn("docker", ["exec", "-it", name, "bash", "-i"]); bash_connections[name].stdout.on('data', function(data) { emit('bash-data', {name: name, type: 'stdout', text: data.toString()}); }); } function bash_start(name) { console.log("-> bash-start("+name+")"); new_bash(name); } function bash_input(data) { console.log("-> bash-input("+data.name+", "+data.text+")"); new_bash(name); bash_connections[data.name].stdin.resume(); bash_connections[data.name].stdin.write(data.text); } function bash_end(name, text) { console.log("-> bash-end("+name+")"); if (!bash_connections[name]) return; bash_connections[name].stdin.close(); delete bash_connections[name]; bash_connections[name] = null; } socket .on("containers", containers) .on("images", images) .on("start", start) .on("stop", stop) .on("pause", pause) .on("unpause", unpause) .on("remove", remove) .on('logs', logs) .on('bash-start', bash_start) .on('bash-input', bash_input) .on('bash-end', bash_end); } return module; }