new features log and bash
This commit is contained in:
@@ -3,10 +3,11 @@
|
|||||||
"version": "@PACKAGE_VERSION@",
|
"version": "@PACKAGE_VERSION@",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "~2.5.8",
|
"express": "~2.5.8",
|
||||||
"stylus": "~0.53.0",
|
"stylus": "~0.53.0",
|
||||||
"ejs": ">= 0.0.1",
|
"ejs": ">= 0.0.1",
|
||||||
"socket.io": "~1.4.4"
|
"socket.io": "~1.4.4",
|
||||||
|
"pty.js": "~0.3.0"
|
||||||
},
|
},
|
||||||
"description": "Docker as a Service",
|
"description": "Docker as a Service",
|
||||||
"main": "servicedock.js",
|
"main": "servicedock.js",
|
||||||
|
@@ -13,11 +13,11 @@ var focused = null;
|
|||||||
|
|
||||||
function DockerContainers() {
|
function DockerContainers() {
|
||||||
var Status = Object.freeze({
|
var Status = Object.freeze({
|
||||||
Error: {color: "red", action1: "start", action2: "remove"},
|
Error: {color: "red", action1: "start", action2: "remove", bash: false},
|
||||||
Terminated: {color: "yellow", action1: "start", action2: "remove"},
|
Terminated: {color: "yellow", action1: "start", action2: "remove", bash: false},
|
||||||
Restarting: {color: "lightblue", action1: "start", action2: "remove"},
|
Restarting: {color: "lightblue", action1: "start", action2: "remove", bash: false},
|
||||||
Paused: {color: "lightgrey", action1: "unpause", action2: null},
|
Paused: {color: "lightgrey", action1: "unpause", action2: null, bash: false},
|
||||||
Running: {color: "lightgreen", action1: "pause", action2: "stop"}
|
Running: {color: "lightgreen", action1: "pause", action2: "stop", bash: true}
|
||||||
});
|
});
|
||||||
var containers = [];
|
var containers = [];
|
||||||
var nodes = [];
|
var nodes = [];
|
||||||
@@ -40,7 +40,7 @@ function DockerContainers() {
|
|||||||
if (n.status.action1) {
|
if (n.status.action1) {
|
||||||
$("#popup").append('<button id="popup1">'+n.status.action1+'</button>');
|
$("#popup").append('<button id="popup1">'+n.status.action1+'</button>');
|
||||||
$("#popup1").click(function() {
|
$("#popup1").click(function() {
|
||||||
socket.emit(n.status.action1, name);
|
emit(n.status.action1, name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
$("#popup").append('<button id="popup2">'+(focused?"overview":"focus")+'</button>');
|
$("#popup").append('<button id="popup2">'+(focused?"overview":"focus")+'</button>');
|
||||||
@@ -50,11 +50,27 @@ function DockerContainers() {
|
|||||||
if (n.status.action2) {
|
if (n.status.action2) {
|
||||||
$("#popup").append('<button id="popup3">'+n.status.action2+'</button>');
|
$("#popup").append('<button id="popup3">'+n.status.action2+'</button>');
|
||||||
$("#popup3").click(function() {
|
$("#popup3").click(function() {
|
||||||
socket.emit(n.status.action2, name);
|
emit(n.status.action2, name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
$("#popup").append('<br/>');
|
$("#popup").append('<br/>');
|
||||||
$("#popup").append('<button id="popup4">download</button>');
|
$("#popup").append('<button id="popup4">logs</button>');
|
||||||
|
$("#popup4").click(function() {
|
||||||
|
emit("logs", name);
|
||||||
|
});
|
||||||
|
if (n.status.bash) {
|
||||||
|
$("#popup").append('<button id="popup5">bash</button>');
|
||||||
|
$("#popup5").click(function() {
|
||||||
|
emit("bash-start", name);
|
||||||
|
$("#console").show();
|
||||||
|
$("#main").hide();
|
||||||
|
$("#bash").submit(function() {
|
||||||
|
emit("bash-input", {name: name, text: $("#command").val()+"\n"});
|
||||||
|
$("#command").val("");
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$("#popup").append('<button id="popup6">download</button>');
|
||||||
$("#popup").css("position", "fixed");
|
$("#popup").css("position", "fixed");
|
||||||
$("#popup").css("top", e.pageY-$("#popup").height()/4);
|
$("#popup").css("top", e.pageY-$("#popup").height()/4);
|
||||||
$("#popup").css("left", e.pageX-$("#popup").width()/2);
|
$("#popup").css("left", e.pageX-$("#popup").width()/2);
|
||||||
@@ -66,49 +82,6 @@ function DockerContainers() {
|
|||||||
$("#popup").show();
|
$("#popup").show();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.details = function(name) {
|
|
||||||
var res = `
|
|
||||||
<div id="tabs">
|
|
||||||
<ul>
|
|
||||||
<li><a href="#tabs-1">Overview</a></li>
|
|
||||||
<li><a href="#tabs-2">Logs</a></li>
|
|
||||||
<li><a href="#tabs-3">Dump</a></li>
|
|
||||||
</ul>
|
|
||||||
<div id="tabs-1">
|
|
||||||
<table class="details docker">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Ports</th>
|
|
||||||
<th>Volumes</th>
|
|
||||||
<th>Links</th>
|
|
||||||
<th>Environments</th>
|
|
||||||
<th>Image</th>
|
|
||||||
<th>Command</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
`;
|
|
||||||
var n = nodes[name];
|
|
||||||
res += `
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div id="tabs-2">
|
|
||||||
</div>
|
|
||||||
<div id="tabs-3">
|
|
||||||
<pre>`;
|
|
||||||
res += JSON.stringify(containers[nodes[name].id], null, 4);
|
|
||||||
res += `
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
$(function() {$("#tabs").tabs();});
|
|
||||||
</script>
|
|
||||||
`;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
function getIps(n, ips) {
|
function getIps(n, ips) {
|
||||||
n.ports.forEach(function(p) {
|
n.ports.forEach(function(p) {
|
||||||
if (!ips[p.ip]) ips[p.ip] = [];
|
if (!ips[p.ip]) ips[p.ip] = [];
|
||||||
@@ -243,7 +216,6 @@ function DockerContainers() {
|
|||||||
else if (c.State.Restarting) nodes[name].status = Status.Restarting;
|
else if (c.State.Restarting) nodes[name].status = Status.Restarting;
|
||||||
else if (c.State.ExitCode == 0) nodes[name].status = Status.Terminated;
|
else if (c.State.ExitCode == 0) nodes[name].status = Status.Terminated;
|
||||||
else nodes[name].status = Status.Error;
|
else nodes[name].status = Status.Error;
|
||||||
console.log("STATUS", name, c.State, nodes[name].status);
|
|
||||||
nodes[name].volumes = [];
|
nodes[name].volumes = [];
|
||||||
var volumes = c.Volumes || c.Config.Volumes;
|
var volumes = c.Volumes || c.Config.Volumes;
|
||||||
nodes[name].volumes = [];
|
nodes[name].volumes = [];
|
||||||
@@ -316,6 +288,14 @@ function DockerContainers() {
|
|||||||
|
|
||||||
var dc = new DockerContainers();
|
var dc = new DockerContainers();
|
||||||
|
|
||||||
|
function htmlenc(html) {
|
||||||
|
return $('<div/>').text(html).html();
|
||||||
|
}
|
||||||
|
|
||||||
|
function htmldec(data) {
|
||||||
|
return $('<div/>').html(data).text();
|
||||||
|
}
|
||||||
|
|
||||||
/// Show error messsage
|
/// Show error messsage
|
||||||
/** Fades in an error message and logs to console.
|
/** Fades in an error message and logs to console.
|
||||||
@param data (optional) The error can be a string or any structure.
|
@param data (optional) The error can be a string or any structure.
|
||||||
@@ -389,6 +369,7 @@ function status(text, msg) {
|
|||||||
$("#popup").hide();
|
$("#popup").hide();
|
||||||
if (msg) success(msg);
|
if (msg) success(msg);
|
||||||
else setTimeout("$('#status').fadeOut('slow')", 5000);
|
else setTimeout("$('#status').fadeOut('slow')", 5000);
|
||||||
|
zoom(0);
|
||||||
$("#main").show();
|
$("#main").show();
|
||||||
$("form input:first-child").focus();
|
$("form input:first-child").focus();
|
||||||
dc.contextmenu("#main");
|
dc.contextmenu("#main");
|
||||||
@@ -488,7 +469,6 @@ function showviz(vizpath, more) {
|
|||||||
}
|
}
|
||||||
res = "digraph {\n"+" rankdir="+rankdir+";\n"+viz+"\n}";
|
res = "digraph {\n"+" rankdir="+rankdir+";\n"+viz+"\n}";
|
||||||
try {
|
try {
|
||||||
zoomlevel = 0;
|
|
||||||
status(more?Viz(res)+more:Viz(res));
|
status(more?Viz(res)+more:Viz(res));
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
(res = res.split("\n")).forEach(function(v, i, a) {
|
(res = res.split("\n")).forEach(function(v, i, a) {
|
||||||
@@ -504,43 +484,6 @@ function details(name) {
|
|||||||
showviz(dc.subgraph(focused));
|
showviz(dc.subgraph(focused));
|
||||||
}
|
}
|
||||||
|
|
||||||
function action(container, action) {
|
|
||||||
$("#imagetools").hide();
|
|
||||||
$.ajax({url: "action.php?container="+container+"&action="+action, success: function(res) {
|
|
||||||
success(res);
|
|
||||||
manage();
|
|
||||||
}}).fail(function() {
|
|
||||||
error("offline");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Manage Docker Services */
|
|
||||||
function manage() {
|
|
||||||
$("#imagetools").hide();
|
|
||||||
$.ajax({url: "manage.php", success: function(res) {
|
|
||||||
status(res);
|
|
||||||
}}).fail(function() {
|
|
||||||
error("offline");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Show an Overview of all Docker Images */
|
|
||||||
function imgs() {
|
|
||||||
$("#imagetools").hide();
|
|
||||||
$.ajax({url: "images.php", success: function(res) {
|
|
||||||
try {
|
|
||||||
showviz(res);
|
|
||||||
} catch(e) {
|
|
||||||
(res = res.split("\n")).forEach(function(v, i, a) {
|
|
||||||
a[i] = ("000"+(i+1)).slice(-3)+": "+v;
|
|
||||||
});
|
|
||||||
status("<h2>Exception Caught:</h2><p>"+e+"<p><pre>"+res.join("\n")+"</pre>");
|
|
||||||
}
|
|
||||||
}}).fail(function() {
|
|
||||||
error("offline");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function containers(c) {
|
function containers(c) {
|
||||||
console.log("->rcv containers");
|
console.log("->rcv containers");
|
||||||
dc.setContainers(c);
|
dc.setContainers(c);
|
||||||
@@ -550,6 +493,109 @@ function containers(c) {
|
|||||||
overview();
|
overview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function logs(data) {
|
||||||
|
console.log("->rcv logs("+data.name+")");
|
||||||
|
$("#main").hide();
|
||||||
|
$("#console").hide();
|
||||||
|
$("#logs").show();
|
||||||
|
if (data.type=='done') {
|
||||||
|
$("#logs").append('<span class="'+data.type+'">\nDONE</span>');
|
||||||
|
} else {
|
||||||
|
$("#logs").append('<span class="'+data.type+'">'+htmlenc(data.text)+'</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function strInsert(str, pos, txt) {
|
||||||
|
return str.slice(0, pos)+txt+str.slice(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ansifilter(data) {
|
||||||
|
console.log("ansifilter");
|
||||||
|
var res = data;
|
||||||
|
var pos = -1;
|
||||||
|
var spans = 0;
|
||||||
|
while ((pos=res.indexOf("\x1B[")) >= 0) {
|
||||||
|
var end = res.indexOf("m", pos+2);
|
||||||
|
if (end>0) {
|
||||||
|
var control= res.slice(pos+2, end);
|
||||||
|
res = res.slice(0, pos)+res.slice(end+1);
|
||||||
|
control.split(';').forEach(function(c) {
|
||||||
|
switch (parseInt(c)) {
|
||||||
|
// set
|
||||||
|
case 1: res = strInsert(res, pos, '<span class="bold">'); ++spans; break;
|
||||||
|
case 2: res = strInsert(res, pos, '<span class="dim">'); ++spans; break;
|
||||||
|
case 4: res = strInsert(res, pos, '<span class="underlined">'); ++spans; break;
|
||||||
|
case 5: res = strInsert(res, pos, '<span class="blink">'); ++spans; break;
|
||||||
|
case 7: res = strInsert(res, pos, '<span class="reverse">'); ++spans; break;
|
||||||
|
case 8: res = strInsert(res, pos, '<span class="hidden">'); ++spans; break;
|
||||||
|
// reset
|
||||||
|
case 0: for (;spans;--spans) res = strInsert(res, pos, "</span>"); break;
|
||||||
|
case 21: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
|
||||||
|
case 22: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
|
||||||
|
case 23: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
|
||||||
|
case 25: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
|
||||||
|
case 27: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
|
||||||
|
case 28: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
|
||||||
|
// fg colors
|
||||||
|
case 39: res = strInsert(res, pos, '<span class="fgdefault">'); ++spans; break;
|
||||||
|
case 30: res = strInsert(res, pos, '<span class="fgblack">'); ++spans; break;
|
||||||
|
case 31: res = strInsert(res, pos, '<span class="fgred">'); ++spans; break;
|
||||||
|
case 32: res = strInsert(res, pos, '<span class="fggreen">'); ++spans; break;
|
||||||
|
case 33: res = strInsert(res, pos, '<span class="fgyellow">'); ++spans; break;
|
||||||
|
case 34: res = strInsert(res, pos, '<span class="fgblue">'); ++spans; break;
|
||||||
|
case 35: res = strInsert(res, pos, '<span class="fgmagenta">'); ++spans; break;
|
||||||
|
case 36: res = strInsert(res, pos, '<span class="fgcyan">'); ++spans; break;
|
||||||
|
case 37: res = strInsert(res, pos, '<span class="fglightgrey">'); ++spans; break;
|
||||||
|
case 90: res = strInsert(res, pos, '<span class="fgdarkgrey">'); ++spans; break;
|
||||||
|
case 91: res = strInsert(res, pos, '<span class="fglightred">'); ++spans; break;
|
||||||
|
case 92: res = strInsert(res, pos, '<span class="fglightgreen">'); ++spans; break;
|
||||||
|
case 93: res = strInsert(res, pos, '<span class="fglightyellow">'); ++spans; break;
|
||||||
|
case 94: res = strInsert(res, pos, '<span class="fglightblue">'); ++spans; break;
|
||||||
|
case 95: res = strInsert(res, pos, '<span class="fglightmagenta">'); ++spans; break;
|
||||||
|
case 96: res = strInsert(res, pos, '<span class="fglightcyan">'); ++spans; break;
|
||||||
|
case 97: res = strInsert(res, pos, '<span class="fgwhite">'); ++spans; break;
|
||||||
|
// bg colors
|
||||||
|
case 49: res = strInsert(res, pos, '<span class="bgdefault">'); ++spans; break;
|
||||||
|
case 40: res = strInsert(res, pos, '<span class="bgblack">'); ++spans; break;
|
||||||
|
case 41: res = strInsert(res, pos, '<span class="bgred">'); ++spans; break;
|
||||||
|
case 42: res = strInsert(res, pos, '<span class="bggreen">'); ++spans; break;
|
||||||
|
case 43: res = strInsert(res, pos, '<span class="bgyellow">'); ++spans; break;
|
||||||
|
case 44: res = strInsert(res, pos, '<span class="bgblue">'); ++spans; break;
|
||||||
|
case 45: res = strInsert(res, pos, '<span class="bgmagenta">'); ++spans; break;
|
||||||
|
case 46: res = strInsert(res, pos, '<span class="bgcyan">'); ++spans; break;
|
||||||
|
case 47: res = strInsert(res, pos, '<span class="bglightgrey">'); ++spans; break;
|
||||||
|
case 100: res = strInsert(res, pos, '<span class="bgdarkgrey">'); ++spans; break;
|
||||||
|
case 101: res = strInsert(res, pos, '<span class="bglightred">'); ++spans; break;
|
||||||
|
case 102: res = strInsert(res, pos, '<span class="bglightgreen">'); ++spans; break;
|
||||||
|
case 103: res = strInsert(res, pos, '<span class="bglightyellow">'); ++spans; break;
|
||||||
|
case 104: res = strInsert(res, pos, '<span class="bglightblue">'); ++spans; break;
|
||||||
|
case 105: res = strInsert(res, pos, '<span class="bglightmagenta">'); ++spans; break;
|
||||||
|
case 106: res = strInsert(res, pos, '<span class="bglightcyan">'); ++spans; break;
|
||||||
|
case 107: res = strInsert(res, pos, '<span class="bgwhite">'); ++spans; break;
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (;spans;--spans) res += "</span>";
|
||||||
|
console.log(res);
|
||||||
|
return res.replace(/\r\r\n/g, '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function bash_data(data) {
|
||||||
|
console.log("->rcv bash-data("+data.name+")", data);
|
||||||
|
$("#main").hide();
|
||||||
|
$("#logs").hide();
|
||||||
|
$("#console").show();
|
||||||
|
if (data.type=='done') {
|
||||||
|
$("#screen").append('<span class="'+data.type+'">\nDONE</span>');
|
||||||
|
} else {
|
||||||
|
$("#screen").append('<span class="'+data.type+'">'+ansifilter(htmlenc(data.text))+'</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function overview() {
|
function overview() {
|
||||||
focused = null;
|
focused = null;
|
||||||
showviz(dc.graph());
|
showviz(dc.graph());
|
||||||
@@ -577,7 +623,9 @@ function init() {
|
|||||||
.on("error", disconnected);
|
.on("error", disconnected);
|
||||||
socket
|
socket
|
||||||
.on("fail", error)
|
.on("fail", error)
|
||||||
.on("containers", containers);
|
.on("containers", containers)
|
||||||
|
.on("logs", logs)
|
||||||
|
.on("bash-data", bash_data);
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,6 +3,10 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-resolution: 120dpi) {
|
@media (min-resolution: 120dpi) {
|
||||||
html {
|
html {
|
||||||
font-size: 120%;
|
font-size: 120%;
|
||||||
@@ -228,18 +232,22 @@ table.docker li+li {
|
|||||||
padding-top: 0.5em;
|
padding-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main {
|
#main, #logs, #console {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 2em;
|
top: 1.5em;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 2em;
|
bottom: 1.5em;
|
||||||
padding: 0em 1em 0em 1em;
|
padding: 1em 1em 1em 1em;
|
||||||
clear: both;
|
clear: both;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
#popup {
|
#popup {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
background-color: lightblue;
|
background-color: lightblue;
|
||||||
@@ -308,3 +316,62 @@ table.docker li+li {
|
|||||||
#preview img {
|
#preview img {
|
||||||
height: 4em;
|
height: 4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#logs {
|
||||||
|
background-color: lightgray;
|
||||||
|
}
|
||||||
|
#logs .stdout {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.stderr {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
.done {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
#console {
|
||||||
|
background-color: black;
|
||||||
|
color: white
|
||||||
|
}
|
||||||
|
.bold {font-weight: bold}
|
||||||
|
.dim {color: grey}
|
||||||
|
.underline {text-decoration: underline}
|
||||||
|
.blink {animation: blinker 1s linear infinite}
|
||||||
|
@keyframes blinker {50% { opacity: 0.0;}}
|
||||||
|
.reverse {color: black; background-color: white}
|
||||||
|
.hidden {color: black}
|
||||||
|
.fgdefault {color: white}
|
||||||
|
.fgblack {color: black}
|
||||||
|
.fgred {color: red}
|
||||||
|
.fggreen {color: green}
|
||||||
|
.fgyellow {color: yellow}
|
||||||
|
.fgblue {color: blue}
|
||||||
|
.fgmagenta {color: magenta}
|
||||||
|
.fgcyan {color: cyan}
|
||||||
|
.fglightgrey {color: lightgrey}
|
||||||
|
.fgdarkgrey {color: darkgrey}
|
||||||
|
.fglightred {color: lightred}
|
||||||
|
.fglightgreen {color: lightgreen}
|
||||||
|
.fglightyellow {color: lightyellow}
|
||||||
|
.fglightblue {color: lightblue}
|
||||||
|
.fglightmagenta {color: lightmagenta}
|
||||||
|
.fglightcyan {color: lightcyan}
|
||||||
|
.fgwhite {color: white}
|
||||||
|
.bgdefault {background-color: black}
|
||||||
|
.bgblack {background-color: black}
|
||||||
|
.bgred {background-color: red}
|
||||||
|
.bggreen {background-color: green}
|
||||||
|
.bgyellow {background-color: yellow}
|
||||||
|
.bgblue {background-color: blue}
|
||||||
|
.bgmagenta {background-color: magenta}
|
||||||
|
.bgcyan {background-color: cyan}
|
||||||
|
.bglightgrey {background-color: lightgrey}
|
||||||
|
.bgdarkgrey {background-color: darkgrey}
|
||||||
|
.bglightred {background-color: lightred}
|
||||||
|
.bglightgreen {background-color: lightgreen}
|
||||||
|
.bglightyellow {background-color: lightyellow}
|
||||||
|
.bglightblue {background-color: lightblue}
|
||||||
|
.bglightmagenta {background-color: lightmagenta}
|
||||||
|
.bglightcyan {background-color: lightcyan}
|
||||||
|
.bgwhite {background-color: white}
|
||||||
|
@@ -5,6 +5,7 @@ module.exports = function() {
|
|||||||
module.connection = function(socket) {
|
module.connection = function(socket) {
|
||||||
|
|
||||||
//var sys = require('sys');
|
//var sys = require('sys');
|
||||||
|
var pty = require('pty.js');
|
||||||
var proc = require('child_process');
|
var proc = require('child_process');
|
||||||
|
|
||||||
console.log("new client");
|
console.log("new client");
|
||||||
@@ -60,9 +61,7 @@ module.exports = function() {
|
|||||||
|
|
||||||
function modify(cmd, name) {
|
function modify(cmd, name) {
|
||||||
if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i))
|
if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i))
|
||||||
return fail("illegal instance name", {
|
return fail("illegal instance name");
|
||||||
error: error, stderr: stderr, stdout: stdout
|
|
||||||
});
|
|
||||||
exec("docker "+cmd+" "+name, updatecontainers);
|
exec("docker "+cmd+" "+name, updatecontainers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,13 +95,61 @@ module.exports = function() {
|
|||||||
modify("rm", 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 bash_start(name) {
|
||||||
|
console.log("-> bash-start("+name+")");
|
||||||
|
if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i))
|
||||||
|
return fail("illegal instance name");
|
||||||
|
if (bash_connections[name]) return fail("bash already open");
|
||||||
|
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()});
|
||||||
|
});
|
||||||
|
// bash_connections[name].stderr.on('data', function(data) {
|
||||||
|
// emit('bash-data', {name: name, type: 'stdout', text: data.toString()});
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
function bash_input(data) {
|
||||||
|
console.log("-> bash-input("+data.name+", "+data.text+")");
|
||||||
|
if (!bash_connections[data.name]) return fail("bash not open");
|
||||||
|
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 fail("bash not open");
|
||||||
|
// bash_connections[name].stdin.close();
|
||||||
|
// }
|
||||||
|
|
||||||
socket
|
socket
|
||||||
.on("containers", containers)
|
.on("containers", containers)
|
||||||
.on("start", start)
|
.on("start", start)
|
||||||
.on("stop", stop)
|
.on("stop", stop)
|
||||||
.on("pause", pause)
|
.on("pause", pause)
|
||||||
.on("unpause", unpause)
|
.on("unpause", unpause)
|
||||||
.on("remove", remove);
|
.on("remove", remove)
|
||||||
|
.on('logs', logs)
|
||||||
|
.on('bash-start', bash_start)
|
||||||
|
.on('bash-input', bash_input);
|
||||||
|
//.on('bash-end', bash_end);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,6 +44,16 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<pre id="logs" style="display: none"> </pre>
|
||||||
|
|
||||||
|
<div id="console" style="display: none">
|
||||||
|
<pre id="screen"></pre>
|
||||||
|
<form id="bash">
|
||||||
|
<input placeholder="command" type="text" id="command">
|
||||||
|
<input type="submit">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="status">
|
<div id="status">
|
||||||
|
|
||||||
<noscript>JavaScript is required for the interface.</noscript>
|
<noscript>JavaScript is required for the interface.</noscript>
|
||||||
|
Reference in New Issue
Block a user