Merge branch 'master' into patch-3

This commit is contained in:
tom mortensen
2018-03-17 11:08:33 -07:00
committed by GitHub
11 changed files with 184 additions and 69 deletions
@@ -12,16 +12,23 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$user_prefs = '/boot/config/plugins/dockerMan/userprefs.cfg';
exec("docker ps -a --format='{{.Names}}'",$container);
exec("docker ps -a --format='{{.Names}}'",$all_containers);
if (file_exists($user_prefs)) {
$prefs = parse_ini_file($user_prefs); $sort = [];
foreach ($all_containers as $ct) $sort[] = array_search($ct,$prefs) ?? 999;
array_multisort($sort,SORT_NUMERIC,$all_containers);
}
$action = $_POST['action'];
switch ($action) {
case 'stop' : $state = 'true'; break;
case 'stop' : $state = 'true'; $all_containers = array_reverse($all_containers); break;
case 'start': $state = 'false'; break;
}
foreach ($container as $ct) {
foreach ($all_containers as $ct) {
if (exec("docker inspect --format='{{.State.Running}}' $ct")==$state) exec("docker $action $ct >/dev/null");
}
?>
@@ -20,6 +20,7 @@ $dockerManPaths = [
'template-repos' => '/boot/config/plugins/dockerMan/template-repos',
'templates-user' => '/boot/config/plugins/dockerMan/templates-user',
'templates-storage' => '/boot/config/plugins/dockerMan/templates',
'user-prefs' => '/boot/config/plugins/dockerMan/userprefs.cfg',
'images-ram' => '/usr/local/emhttp/state/plugins/dynamix.docker.manager/images',
'images-storage' => '/boot/config/plugins/dockerMan/images',
'webui-info' => '/usr/local/emhttp/state/plugins/dynamix.docker.manager/docker.json',
@@ -569,6 +570,9 @@ class DockerUpdate{
######################################
class DockerClient {
private static $allContainersCache = null;
private static $allImagesCache = null;
private function build_sorter($key) {
return function ($a, $b) use ($key) {
return strnatcmp(strtolower($a[$key]), strtolower($b[$key]));
@@ -660,7 +664,7 @@ class DockerClient {
public function startContainer($id) {
$this->getDockerJSON("/containers/${id}/start", 'POST', $code);
DockerUtil::$allContainersCache = null; // flush cache
$this::$allContainersCache = null; // flush cache
$codes = [
'204' => true, // No error
'304' => 'Container already started',
@@ -672,7 +676,7 @@ class DockerClient {
public function stopContainer($id) {
$this->getDockerJSON("/containers/${id}/stop?t=10", 'POST', $code);
DockerUtil::$allContainersCache = null; // flush cache
$this::$allContainersCache = null; // flush cache
$codes = [
'204' => true, // No error
'304' => 'Container already stopped',
@@ -684,7 +688,7 @@ class DockerClient {
public function restartContainer($id) {
$this->getDockerJSON("/containers/${id}/restart?t=10", 'POST', $code);
DockerUtil::$allContainersCache = null; // flush cache
$this::$allContainersCache = null; // flush cache
$codes = [
'204' => true, // No error
'404' => 'No such container',
@@ -709,7 +713,7 @@ class DockerClient {
}
// Attempt to remove container
$this->getDockerJSON("/containers/${id}?force=1", 'DELETE', $code);
DockerUtil::$allContainersCache = null; // flush cache
$this::$allContainersCache = null; // flush cache
$codes = [
'204' => true, // No error
'400' => 'Bad parameter',
@@ -721,7 +725,7 @@ class DockerClient {
public function pullImage($image, $callback = null) {
$ret = $this->getDockerJSON("/images/create?fromImage=".urlencode($image), 'POST', $code, $callback);
DockerUtil::$allImagesCache = null; // flush cache
$this::$allImagesCache = null; // flush cache
return $ret;
}
@@ -730,7 +734,7 @@ class DockerClient {
$image = $this->getImageName($id);
// Attempt to remove image
$this->getDockerJSON("/images/${id}?force=1", 'DELETE', $code);
DockerUtil::$allImagesCache = null; // flush cache
$this::$allImagesCache = null; // flush cache
if (in_array($code, ['200', '404'])) {
// Purge cached image information (only if delete was successful)
$image = DockerUtil::ensureImageTag($image);
@@ -755,8 +759,8 @@ class DockerClient {
public function getDockerContainers() {
// Return cached values
if (is_array(DockerUtil::$allContainersCache)) return DockerUtil::$allContainersCache;
DockerUtil::$allContainersCache = [];
if (is_array($this::$allContainersCache)) return $this::$allContainersCache;
$this::$allContainersCache = [];
foreach ($this->getDockerJSON("/containers/json?all=1") as $obj) {
$details = $this->getContainerDetails($obj['Id']);
$c = [];
@@ -778,10 +782,10 @@ class DockerClient {
$c['Ports'][] = ['IP' => $value[0]['HostIP'] ?? '0.0.0.0', 'PrivatePort' => $PrivatePort, 'PublicPort' => $value[0]['HostPort'], 'Type' => $Type ];
}
}
DockerUtil::$allContainersCache[] = $c;
$this::$allContainersCache[] = $c;
}
usort(DockerUtil::$allContainersCache, $this->build_sorter('Name'));
return DockerUtil::$allContainersCache;
usort($this::$allContainersCache, $this->build_sorter('Name'));
return $this::$allContainersCache;
}
public function getContainerID($Container) {
@@ -818,8 +822,8 @@ class DockerClient {
public function getDockerImages() {
// Return cached values
if (is_array(DockerUtil::$allImagesCache)) return DockerUtil::$allImagesCache;
DockerUtil::$allImagesCache = [];
if (is_array($this::$allImagesCache)) return $this::$allImagesCache;
$this::$allImagesCache = [];
foreach ($this->getDockerJSON('/images/json?all=0') as $obj) {
$c = [];
$c['Created'] = $this->humanTiming($obj['Created']);
@@ -830,14 +834,14 @@ class DockerClient {
$c['Tags'] = array_map('htmlspecialchars', $obj['RepoTags'] ?? []);
$c['Repository'] = vsprintf('%1$s/%2$s', preg_split("#[:\/]#", DockerUtil::ensureImageTag($obj['RepoTags'][0])));
$c['usedBy'] = $this->usedBy($c['Id']);
DockerUtil::$allImagesCache[$c['Id']] = $c;
$this::$allImagesCache[$c['Id']] = $c;
}
return DockerUtil::$allImagesCache;
return $this::$allImagesCache;
}
public function flushCaches() {
DockerUtil::$allContainersCache = null;
DockerUtil::$allImagesCache = null;
$this::$allContainersCache = null;
$this::$allImagesCache = null;
}
}
@@ -846,9 +850,6 @@ class DockerClient {
######################################
class DockerUtil {
public static $allContainersCache = null;
public static $allImagesCache = null;
public static function ensureImageTag($image) {
list($strRepo, $strTag) = explode(':', $image.':');
if (strpos($strRepo, 'sha256:') === 0) {
@@ -17,6 +17,7 @@ $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
// Add the Docker JSON client
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
$user_prefs = $dockerManPaths['user-prefs'];
$DockerClient = new DockerClient();
$DockerTemplates = new DockerTemplates();
@@ -26,17 +27,23 @@ if (!$all_containers) {
return;
}
if (file_exists($user_prefs)) {
$prefs = parse_ini_file($user_prefs); $sort = [];
foreach ($all_containers as $ct) $sort[] = array_search($ct['Name'],$prefs) ?? 999;
array_multisort($sort,SORT_NUMERIC,$all_containers);
}
// Read network settings
extract(parse_ini_file('state/network.ini',true));
// Read container info
$all = $DockerTemplates->getAllInfo();
$all_info = $DockerTemplates->getAllInfo();
$menu = [];
$docker = ['var docker=[];'];
foreach ($all_containers as $ct) {
$name = $ct['Name'];
$info = &$all[$name];
$info = &$all_info[$name];
$mode = $ct['NetworkMode'];
$id = $ct['Id'];
$imageID = $ct['ImageId'];
@@ -80,7 +87,7 @@ foreach ($all_containers as $ct) {
echo "<div id='$id' style='display:block; cursor:pointer'><div style='position:relative;width:48px;height:48px;margin:0px auto'>";
echo "<img src='".htmlspecialchars($icon)."' class='".htmlspecialchars($status)."' style='position:absolute;top:0;bottom:0;left:0;right:0;width:48px;height:48px'>";
echo "<i class='fa iconstatus fa-$shape $status' title='".htmlspecialchars($status)."'></i></div></div>";
echo "</td><td>";
echo "</td><td class='ct-name'>";
if ($template) {
echo "<a class='exec' onclick=\"editContainer('".addslashes(htmlspecialchars($name))."','".addslashes(htmlspecialchars($template))."')\">".htmlspecialchars($name)."</a>";
} else {
@@ -109,7 +116,9 @@ foreach ($all_containers as $ct) {
echo "<td style='white-space:nowrap'><span class='docker_readmore'>".implode('<br>',$ports)."</span></td>";
echo "<td style='word-break:break-all'><span class='docker_readmore'>".implode('<br>',$paths)."</span></td>";
echo "<td><input type='checkbox' class='autostart' container='".htmlspecialchars($name)."'".($info['autostart'] ? ' checked':'')."></td>";
echo "<td><a class='log' onclick=\"containerLogs('".addslashes(htmlspecialchars($name))."','$id',false,false)\"><img class='basic' src='/plugins/dynamix/icons/log.png'><div class='advanced' style='width:124px;'>".htmlspecialchars(str_replace('Up','Uptime',$ct['Status']))."</div><div class='advanced'>Created ".htmlspecialchars($ct['Created'])."</div></a></td></tr>";
echo "<td><a class='log' onclick=\"containerLogs('".addslashes(htmlspecialchars($name))."','$id',false,false)\"><img class='basic' src='/plugins/dynamix/icons/log.png'><div class='advanced'>";
echo htmlspecialchars(str_replace('Up','Uptime',$ct['Status']))."</div><div class='advanced' style='margin-top:4px'>Created ".htmlspecialchars($ct['Created'])."</div></a></td>";
echo "<td style='text-align:right;padding-right:12px'><a href='#' title='Move row up'><i class='fa fa-arrow-up up'></i></a>&nbsp;<a href='#' title='Move row down'><i class='fa fa-arrow-down down'></i></a></td></tr>";
}
foreach ($DockerClient->getDockerImages() as $image) {
if (count($image['usedBy'])) continue;
@@ -1,6 +1,7 @@
<?PHP
/* Copyright 2005-2017, Lime Technology
* Copyright 2014-2017, Guilherme Jardim, Eric Schultz, Jon Panozzo.
/* Copyright 2005-2018, Lime Technology
* Copyright 2014-2018, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2018, Bergware International.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
@@ -14,13 +15,12 @@
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
// Autostart file
global $dockerManPaths;
$autostart_file = $dockerManPaths['autostart-file'];
$template_repos = $dockerManPaths['template-repos'];
$user_prefs = $dockerManPaths['user-prefs'];
// Update the start/stop configuration
if ($_POST['action'] == "autostart" ){
if ($_POST['action'] == 'autostart' ){
$json = ($_POST['response'] == 'json') ? true : false;
if (!$json) readfile("$docroot/update.htm");
@@ -28,21 +28,27 @@ if ($_POST['action'] == "autostart" ){
$container = urldecode(($_POST['container']));
unset($_POST['container']);
$allAutoStart = @file($autostart_file, FILE_IGNORE_NEW_LINES);
if ($allAutoStart===FALSE) $allAutoStart = [];
$allAutoStart = @file($autostart_file, FILE_IGNORE_NEW_LINES) ?: [];
$key = array_search($container, $allAutoStart);
if ($key===FALSE) {
if ($key===false) {
array_push($allAutoStart, $container);
if ($json) echo json_encode(['autostart' => true]);
}
else {
} else {
unset($allAutoStart[$key]);
if ($json) echo json_encode(['autostart' => false]);
}
file_put_contents($autostart_file, implode(PHP_EOL, $allAutoStart).(count($allAutoStart)? PHP_EOL : ""));
// sort containers for start-up
if (file_exists($user_prefs)) {
$prefs = parse_ini_file($user_prefs); $sort = [];
foreach ($allAutoStart as $ct) $sort[] = array_search($ct,$prefs) ?? 999;
array_multisort($sort,SORT_NUMERIC,$allAutoStart);
} else {
natcasesort($allAutoStart);
}
$allAutoStart ? file_put_contents($autostart_file, implode(PHP_EOL, $allAutoStart).PHP_EOL) : @unlink($autostart_file);
}
if ($_POST['#action'] == "templates" ){
if ($_POST['#action'] == 'templates' ){
readfile("$docroot/update.htm");
$repos = $_POST['template_repos'];
file_put_contents($template_repos, $repos);
@@ -0,0 +1,45 @@
<?PHP
/* Copyright 2005-2018, Lime Technology
* Copyright 2015-2018, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2018, Bergware International.
*
* 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.
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
$autostart_file = $dockerManPaths['autostart-file'];
$user_prefs = $dockerManPaths['user-prefs'];
if (isset($_POST['reset'])) {
@unlink($user_prefs);
if (file_exists($autostart_file)) {
$allAutoStart = file($autostart_file, FILE_IGNORE_NEW_LINES);
natcasesort($allAutoStart);
file_put_contents($autostart_file, implode(PHP_EOL, $allAutoStart).PHP_EOL);
}
} else {
$names = explode(';',$_POST['names']);
$index = explode(';',$_POST['index']);
$save = []; $i = 0;
foreach ($names as $name) if ($name) $save[] = $index[$i++]."=\"".$name."\""; else $i++;
file_put_contents($user_prefs, implode("\n",$save)."\n");
// sort containers for start-up
if (file_exists($autostart_file)) {
$prefs = parse_ini_file($user_prefs); $sort = [];
$allAutoStart = file($autostart_file, FILE_IGNORE_NEW_LINES);
foreach ($allAutoStart as $ct) $sort[] = array_search($ct,$prefs) ?? 999;
array_multisort($sort,SORT_NUMERIC,$allAutoStart);
file_put_contents($autostart_file, implode(PHP_EOL, $allAutoStart).PHP_EOL);
}
}
?>