new features log and bash
This commit is contained in:
		@@ -3,10 +3,11 @@
 | 
			
		||||
  "version": "@PACKAGE_VERSION@",
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "express": "~2.5.8",
 | 
			
		||||
    "stylus": "~0.53.0",
 | 
			
		||||
    "ejs": ">= 0.0.1",
 | 
			
		||||
    "socket.io": "~1.4.4"
 | 
			
		||||
      "express": "~2.5.8",
 | 
			
		||||
      "stylus": "~0.53.0",
 | 
			
		||||
      "ejs": ">= 0.0.1",
 | 
			
		||||
      "socket.io": "~1.4.4",
 | 
			
		||||
      "pty.js": "~0.3.0"
 | 
			
		||||
  },
 | 
			
		||||
  "description": "Docker as a Service",
 | 
			
		||||
  "main": "servicedock.js",
 | 
			
		||||
 
 | 
			
		||||
@@ -13,11 +13,11 @@ var focused = null;
 | 
			
		||||
 | 
			
		||||
function DockerContainers() {
 | 
			
		||||
    var Status = Object.freeze({
 | 
			
		||||
        Error:      {color: "red", action1: "start", action2: "remove"},
 | 
			
		||||
        Terminated: {color: "yellow", action1: "start", action2: "remove"},
 | 
			
		||||
        Restarting: {color: "lightblue", action1: "start", action2: "remove"},
 | 
			
		||||
        Paused:     {color: "lightgrey", action1: "unpause", action2: null},
 | 
			
		||||
        Running:    {color: "lightgreen", action1: "pause", action2: "stop"}
 | 
			
		||||
        Error:      {color: "red", action1: "start", action2: "remove", bash: false},
 | 
			
		||||
        Terminated: {color: "yellow", action1: "start", action2: "remove", bash: false},
 | 
			
		||||
        Restarting: {color: "lightblue", action1: "start", action2: "remove", bash: false},
 | 
			
		||||
        Paused:     {color: "lightgrey", action1: "unpause", action2: null, bash: false},
 | 
			
		||||
        Running:    {color: "lightgreen", action1: "pause", action2: "stop", bash: true}
 | 
			
		||||
    });
 | 
			
		||||
    var containers = [];
 | 
			
		||||
    var nodes = [];
 | 
			
		||||
@@ -40,7 +40,7 @@ function DockerContainers() {
 | 
			
		||||
            if (n.status.action1) {
 | 
			
		||||
                $("#popup").append('<button id="popup1">'+n.status.action1+'</button>');
 | 
			
		||||
                $("#popup1").click(function() {
 | 
			
		||||
                    socket.emit(n.status.action1, name);
 | 
			
		||||
                    emit(n.status.action1, name);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            $("#popup").append('<button id="popup2">'+(focused?"overview":"focus")+'</button>');
 | 
			
		||||
@@ -50,11 +50,27 @@ function DockerContainers() {
 | 
			
		||||
            if (n.status.action2) {
 | 
			
		||||
                $("#popup").append('<button id="popup3">'+n.status.action2+'</button>');
 | 
			
		||||
                $("#popup3").click(function() {
 | 
			
		||||
                    socket.emit(n.status.action2, name);
 | 
			
		||||
                    emit(n.status.action2, name);
 | 
			
		||||
            });
 | 
			
		||||
            }
 | 
			
		||||
            $("#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("top", e.pageY-$("#popup").height()/4);
 | 
			
		||||
            $("#popup").css("left", e.pageX-$("#popup").width()/2);
 | 
			
		||||
@@ -66,49 +82,6 @@ function DockerContainers() {
 | 
			
		||||
            $("#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) {
 | 
			
		||||
        n.ports.forEach(function(p) {
 | 
			
		||||
            if (!ips[p.ip]) ips[p.ip] = [];
 | 
			
		||||
@@ -185,7 +158,7 @@ function DockerContainers() {
 | 
			
		||||
        n = n || nodes;
 | 
			
		||||
        for (name in n) getIps(n[name], ips);
 | 
			
		||||
        res += graphIpClusters(ips);
 | 
			
		||||
        for (name in n) res += graphNode(n[name]);        
 | 
			
		||||
        for (name in n) res += graphNode(n[name]);
 | 
			
		||||
        res += "{rank=same;\n";
 | 
			
		||||
        for (name in n) res += graphVolumesInside(n[name]);
 | 
			
		||||
        res+="}\n";
 | 
			
		||||
@@ -243,7 +216,6 @@ function DockerContainers() {
 | 
			
		||||
            else if (c.State.Restarting) nodes[name].status = Status.Restarting;
 | 
			
		||||
            else if (c.State.ExitCode == 0) nodes[name].status = Status.Terminated;
 | 
			
		||||
            else nodes[name].status = Status.Error;
 | 
			
		||||
            console.log("STATUS", name, c.State, nodes[name].status);
 | 
			
		||||
            nodes[name].volumes = [];
 | 
			
		||||
            var volumes = c.Volumes || c.Config.Volumes;
 | 
			
		||||
            nodes[name].volumes = [];
 | 
			
		||||
@@ -316,6 +288,14 @@ function DockerContainers() {
 | 
			
		||||
 | 
			
		||||
var dc = new DockerContainers();
 | 
			
		||||
 | 
			
		||||
function htmlenc(html) {
 | 
			
		||||
    return $('<div/>').text(html).html();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function htmldec(data) {
 | 
			
		||||
    return $('<div/>').html(data).text();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Show error messsage
 | 
			
		||||
/** Fades in an error message and logs to console.
 | 
			
		||||
    @param data (optional) The error can be a string or any structure.
 | 
			
		||||
@@ -389,6 +369,7 @@ function status(text, msg) {
 | 
			
		||||
    $("#popup").hide();
 | 
			
		||||
    if (msg) success(msg);
 | 
			
		||||
    else setTimeout("$('#status').fadeOut('slow')", 5000);
 | 
			
		||||
    zoom(0);
 | 
			
		||||
    $("#main").show();
 | 
			
		||||
    $("form input:first-child").focus();
 | 
			
		||||
    dc.contextmenu("#main");
 | 
			
		||||
@@ -488,7 +469,6 @@ function showviz(vizpath, more) {
 | 
			
		||||
    }
 | 
			
		||||
    res = "digraph {\n"+"  rankdir="+rankdir+";\n"+viz+"\n}";
 | 
			
		||||
    try {
 | 
			
		||||
        zoomlevel = 0;
 | 
			
		||||
        status(more?Viz(res)+more:Viz(res));
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
        (res = res.split("\n")).forEach(function(v, i, a) {
 | 
			
		||||
@@ -504,43 +484,6 @@ function details(name) {
 | 
			
		||||
    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) {
 | 
			
		||||
    console.log("->rcv containers");
 | 
			
		||||
    dc.setContainers(c);
 | 
			
		||||
@@ -550,6 +493,109 @@ function containers(c) {
 | 
			
		||||
        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() {
 | 
			
		||||
    focused = null;
 | 
			
		||||
    showviz(dc.graph());
 | 
			
		||||
@@ -577,7 +623,9 @@ function init() {
 | 
			
		||||
        .on("error", disconnected);
 | 
			
		||||
    socket
 | 
			
		||||
        .on("fail", error)
 | 
			
		||||
        .on("containers", containers);
 | 
			
		||||
        .on("containers", containers)
 | 
			
		||||
        .on("logs", logs)
 | 
			
		||||
        .on("bash-data", bash_data);
 | 
			
		||||
    start();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,10 @@
 | 
			
		||||
  padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
  background-color: blue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (min-resolution: 120dpi) {
 | 
			
		||||
  html {
 | 
			
		||||
    font-size: 120%;
 | 
			
		||||
@@ -228,18 +232,22 @@ table.docker li+li {
 | 
			
		||||
  padding-top: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#main {
 | 
			
		||||
#main, #logs, #console {
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  top: 2em;
 | 
			
		||||
  top: 1.5em;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  bottom: 2em;
 | 
			
		||||
  padding: 0em 1em 0em 1em;
 | 
			
		||||
  bottom: 1.5em;
 | 
			
		||||
  padding: 1em 1em 1em 1em;
 | 
			
		||||
  clear: both;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  z-index: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#main {
 | 
			
		||||
  background-color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#popup {
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  background-color: lightblue;
 | 
			
		||||
@@ -308,3 +316,62 @@ table.docker li+li {
 | 
			
		||||
#preview img {
 | 
			
		||||
  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) {
 | 
			
		||||
 | 
			
		||||
        //var sys = require('sys');
 | 
			
		||||
        var pty = require('pty.js');
 | 
			
		||||
        var proc = require('child_process');
 | 
			
		||||
 | 
			
		||||
        console.log("new client");
 | 
			
		||||
@@ -60,9 +61,7 @@ module.exports = function() {
 | 
			
		||||
 | 
			
		||||
        function modify(cmd, name) {
 | 
			
		||||
            if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i))
 | 
			
		||||
                return fail("illegal instance name", {
 | 
			
		||||
                    error: error, stderr: stderr, stdout: stdout
 | 
			
		||||
                });
 | 
			
		||||
                return fail("illegal instance name");
 | 
			
		||||
            exec("docker "+cmd+" "+name, updatecontainers);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -96,14 +95,62 @@ module.exports = function() {
 | 
			
		||||
            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
 | 
			
		||||
            .on("containers", containers)
 | 
			
		||||
            .on("start", start)
 | 
			
		||||
            .on("stop", stop)
 | 
			
		||||
            .on("pause", pause)
 | 
			
		||||
            .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);
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return module;
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,16 @@
 | 
			
		||||
      
 | 
			
		||||
    </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">
 | 
			
		||||
      
 | 
			
		||||
      <noscript>JavaScript is required for the interface.</noscript>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user