Files
webgui/plugins/dynamix.docker.manager/DockerContainers.page
2016-05-12 08:49:48 +02:00

266 lines
12 KiB
Plaintext

Menu="Docker:1"
Title="Docker Containers"
Cond="(pgrep('docker')!==false)"
Markdown="false"
---
<?PHP
/* Copyright 2015, Lime Technology
* Copyright 2015, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<?
// Add the Docker JSON client
require_once '/usr/local/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php';
$DockerClient = new DockerClient();
$DockerUpdate = new DockerUpdate();
$DockerTemplates = new DockerTemplates();
?>
<link type="text/css" rel="stylesheet" href="/webGui/styles/jquery.ui.css">
<link type="text/css" rel="stylesheet" href="/webGui/styles/jquery.switchbutton.css">
<link type="text/css" rel="stylesheet" href="/webGui/styles/context.standalone.css">
<style>
body {-webkit-overflow-scrolling: touch;}
img.started{opacity:1.0;}
img.stopped{opacity:0.3;}
.log{cursor:zoom-in;}
.exec{cursor:pointer;}
.fa-custom{font-size: 1.3em;}
.basic{display: block;}
.advanced{display:none;white-space: nowrap;}
.iconstatus{position:absolute;z-index:2;bottom:-4px;right:-4px;font-size:1.2em;text-shadow:0 0 2px #FFF;}
.iconstatus.started{font-size:1.3em;}
.iconstatus.stopped{font-size:1.2em;}
.started{color:#009900;}
.stopped{color:#EF3D47;}
</style>
<form id="formAutostart" method="POST" action="/plugins/dynamix.docker.manager/include/UpdateConfig.php" target="progressFrame">
<input type="hidden" name="action" value="autostart" />
<input type="hidden" name="container" value="none" />
</form>
<form id="formStartStop" method="POST" action="/update.php" target="progressFrame">
<input type="hidden" id="cmdStartStop" name="#command" value="">
<input type="hidden" id="cmdArg1" name="#arg[1]" value="">
<input type="hidden" id="cmdArg2" name="#arg[2]" value="">
</form>
<div id="dialog-confirm" style="display:none;" title="Dialog Title"></div>
<div id="iframe-popup" style="display:none;-webkit-overflow-scrolling:touch;"></div>
<span class="status" style="margin-top: -42px;"><input type="checkbox" class="advancedview"></span>
<table class="tablesorter shift" id="docker_containers">
<thead>
<tr>
<th>&nbsp;</th>
<th>Application</th>
<th>Version</th>
<th>Port Mappings <small>(App to Host)</small></th>
<th>Volume Mappings <small>(App to Host)</small></th>
<th width="80px" style="text-align: center">Autostart</th>
<th>Log</th>
</tr>
</thead>
<tbody id="docker_list">
<?
$all_containers = $DockerClient->getDockerContainers();
if (!$all_containers) {
$all_containers = [];
echo "<tr><td></td><td colspan=\"7\">No Docker Containers Installed</td></tr>";
}
$info = $DockerTemplates->getAllInfo();
$contextMenus = [];
$IP = $eth0["IPADDR:0"];
foreach ($all_containers as $ct) {
$name = $ct["Name"];
$is_autostart = ($info[$name]['autostart']) ? 'true' : 'false';
$updateStatus = $info[$name]['updated'];
$updateStatus = ($updateStatus == "true" || $updateStatus == "undef") ? 'true' : 'false';
$running = ($ct['Running']) ? 'true' : 'false';
$webGuiUrl = $info[$name]['url'];
$contextMenus[] = sprintf("addDockerContainerContext('%s', '%s', '%s', %s, %s, %s, '%s', '%s');", addslashes($ct['Name']), addslashes($ct['ImageId']), addslashes($info[$name]['template']), $running, $updateStatus, $is_autostart, addslashes($webGuiUrl), $ct["Id"]);
$shape = ($ct["Running"]) ? "play" : "square";
$status = ($ct["Running"]) ? "started" : "stopped";
$Icon = $info[$name]['icon'];
if (!$Icon) {
$Icon = "/plugins/dynamix.docker.manager/images/question.png";
}
$ports = [];
foreach ($ct['Ports'] as $p) {
if (strlen($p['PublicPort'])) {
$ipAddr = sprintf("%s:%s", $IP, $p['PublicPort']);
$outFormat = sprintf('<a href="http://%s" target="_blank">%s/%s <i class="fa fa-arrows-h" style="margin: 0 3px"></i> %s</a>', $ipAddr, $p['PrivatePort'], $p['Type'], htmlspecialchars($ipAddr));
} else {
$outFormat = sprintf("%s/%s", $p['PrivatePort'], $p['Type']);
}
$ports[] = $outFormat;
}
$paths = [];
if (count($ct['Volumes'])){
foreach ($ct['Volumes'] as $value) {
if (preg_match('/localtime/', $value) == true) continue;
list($host_path, $container_path, $access_mode) = explode(":", $value);
$tip = 'Container volume \'' . $container_path . '\' has ' . ($access_mode == 'ro' ? 'read-only' : 'read-write') . ' access to Host path \'' . $host_path . '\'';
$paths[] = sprintf('<a href="/Shares/Browse?dir=%s" target="_blank" title="%s">%s <i class="fa fa-%s" style="margin: 0 3px"></i> %s</a>', urlencode($host_path), htmlspecialchars($tip), htmlspecialchars($container_path), ($access_mode == 'ro' ? 'long-arrow-left' : 'arrows-h'), htmlspecialchars($host_path));
}
}
?>
<tr>
<td style="width: 48px; padding: 4px">
<?
echo " <div id=\"context-".htmlspecialchars($name)."\" style=\"display:block; cursor:pointer\">
<div style=\"position: relative; width: 48px; height: 48px; margin: 0px auto;\">
<img src=\"".htmlspecialchars($Icon)."\" class=\"".htmlspecialchars($status)."\" style=\"position: absolute; z-index: 1; top: 0; bottom: 0; left: 0; right: 0; width: 48px; height: 48px;\"/>
<i class=\"fa iconstatus fa-$shape $status\" title=\"".htmlspecialchars($status)."\"></i>
</div>
</div>";
?>
</td>
<td>
<?if($info[$ct['Name']]['template']):?>
<a class="exec" onclick="editContainer('<?=addslashes($ct['Name']);?>','<?=addslashes($info[$ct['Name']]['template']);?>');"><?=htmlspecialchars($ct['Name']);?></a>
<?else:?>
<?=htmlspecialchars($ct['Name']);?>
<?endif;?>
<div class="advanced" style="color:#888; width: 160px;">Container ID: <?=htmlspecialchars($ct['Id']);?></div>
<?if($ct['BaseImage']):?>
<div class="advanced" style="color:#888; width: 160px;"><i class="fa fa-cubes" style="margin-right: 5px"></i><?=${ct[BaseImage]}?></div>
<?endif;?>
<div class="advanced" style="color:#888; width: 160px;">By:
<?if($Registry = $info[$ct['Name']]['registry']):?>
<a href="<?=htmlspecialchars($Registry)?>" target="_blank"><?=htmlspecialchars($ct['Image'])?></a>
<?else:?>
<?=htmlspecialchars($ct['Image']);?>
<?endif;?>
</div>
</td>
<td class="updatecolumn">
<?
$updateStatus = $info[$ct['Name']]['updated'];
if ($updateStatus == "false") {
echo "<a class=\"exec\" onclick=\"updateContainer('" . addslashes($ct["Name"]) . "');\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> update ready</span></a>";
} else if ($updateStatus == "true") {
echo "<span style=\"color:#44B012;white-space:nowrap;\"><i class=\"fa fa-check\"></i> up-to-date</span>";
echo "<div class=\"advanced\"><a class=\"exec\" onclick=\"updateContainer('" . addslashes($ct["Name"]) . "');\" style=\"color:#888;\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> force update</span></a></div>";
} else {
echo "<span style=\"color:#FF2400;white-space:nowrap;\"><i class=\"fa fa-exclamation-triangle\"></i> not available</span>";
echo "<div class=\"advanced\"><a class=\"exec\" onclick=\"updateContainer('" . addslashes($ct["Name"]) . "');\" style=\"color:#888;\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> force update</span></a></div>";
}
?>
</td>
<td style="white-space:nowrap;"><span class="docker_readmore"><?= implode("<br>", $ports); ?></span></td>
<td style="word-break:break-all;"><span class="docker_readmore"><?= implode("<br>", $paths); ?></span></td>
<td data-sort-value="<?=$is_autostart?>"><input type="checkbox" class="autostart" container="<?=htmlspecialchars($ct['Name']);?>" <?=$info[$ct['Name']]['autostart'] ? "checked" : ""?>></td>
<td><a class="log" onclick="containerLogs('<?=addslashes($ct['Name']);?>','<?=$ct['Id'];?>', false, false)"><img class="basic" src="/plugins/dynamix/icons/log.png"/><div class="advanced" style="width: 124px;"><?=htmlspecialchars($ct['Status'])?></div><div class="advanced" style="color:#888;">Created <?=htmlspecialchars($ct['Created'])?></div></a></td>
</tr>
<?}?>
<?
foreach ($DockerClient->getDockerImages() as $image) {
if (count($image['usedBy'])) {
continue;
}
$contextMenus[] = sprintf("addDockerImageContext('%s', '%s');", $image['Id'], implode(', ', $image['Tags']));
?>
<tr class="advanced">
<td style="width: 48px; padding: 4px">
<?
echo " <div id=\"context-".htmlspecialchars($image['Id'])."\" style=\"display:block; cursor:pointer\">
<div style=\"position: relative; width: 48px; height: 48px; margin: 0px auto;\">
<img src=\"/webGui/images/disk.png\" style=\"position: absolute; z-index: 1; opacity: 0.3; top: 0; bottom: 0; left: 0; right: 0; width: 48px; height: 48px;\"/>
</div>
</div>";
?>
</td>
<td data-sort-value="ZZZZZZZZZZZ">
<i>(orphan image)</i>
<div style="color:#888; width: 160px;">Image ID: <?=$image['Id']?></div>
<?if(strpos(implode($image['Tags']), "&lt;none&gt;:&lt;none&gt;") === false):?>
<div style="color:#888; width: 160px;"><?=implode("<br>", $image['Tags'])?></div>
<?endif;?>
</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td><div class="advanced" style="width: 124px; color:#888;">Created <?=$image['Created']?></div></td>
</tr>
<?}?>
</tbody>
</table>
<input type="button" onclick="addContainer()" value="Add Container"/>
<input type="button" onclick="reloadUpdate()" value="Check for Updates"/>
<script src="/webGui/javascript/jquery.switchbutton.js"></script>
<script src="/webGui/javascript/context.js"></script>
<script src="/plugins/dynamix.docker.manager/javascript/docker.js"></script>
<script>
<?if ($display['resize']):?>
function resize(bind) {
var width = [];
var h = $('#docker_list').height();
var s = Math.max(window.innerHeight-300,370);
if (h>s || bind) {
$('#docker_list').height(s);
$('#docker_containers tbody tr:first-child td').each(function(){width.push($(this).width());});
$('#docker_containers thead tr th').each(function(i){$(this).width(width[i]);});
if (!bind) $('#docker_containers thead,#docker_containers tbody').addClass('fixed');
}
}
<?endif;?>
$(function() {
if ($.cookie('docker_listview_mode') == 'advanced') {
$('.advanced').show();
$('.basic').hide();
}
$('.autostart').switchButton({
labels_placement: "right"
});
$('.autostart').change(function () {
$.post( "/plugins/dynamix.docker.manager/include/UpdateConfig.php", { action: "autostart", container: $(this).attr('container'), response: "json" }, function( data ) {
$(this).prop('checked', data.autostart );
}, "json");
});
$('.advancedview').switchButton({
labels_placement: "left",
on_label: 'Advanced View',
off_label: 'Basic View',
checked: $.cookie('docker_listview_mode') == 'advanced'
});
$('.advancedview').change(function () {
$('.advanced').toggle('slow');
$('.basic').toggle('slow');
$.cookie('docker_listview_mode', $('.advancedview').is(':checked') ? 'advanced' : 'basic', { expires: 3650 });
});
<?if ($display['resize']):?>
resize();
$(window).bind('resize',function(){resize(true);});
<?endif;?>
$('#docker_containers').tablesorter( {sortList: [[1,0]], headers: {0: {sorter: false }, 7: {sorter: false }}});
$('#docker_containers tr:even').addClass('odd');
context.init({ preventDoubleContext: false });
<?=implode("\n\t", $contextMenus);?>
$('.docker_readmore').readmore({maxHeight:48, moreLink: '<a href="#" style="text-align:center;"><i class="fa fa-chevron-down"></i></a>', lessLink: '<a href="#" style="text-align:center;"><i class="fa fa-chevron-up"></i></a>'});
});
</script>