diff --git a/plugins/dynamix.docker.manager/DockerContainers.page b/plugins/dynamix.docker.manager/DockerContainers.page index 5ed2309dc..9a9f14224 100644 --- a/plugins/dynamix.docker.manager/DockerContainers.page +++ b/plugins/dynamix.docker.manager/DockerContainers.page @@ -4,44 +4,26 @@ Tag="cubes" Cond="(pgrep('dockerd')!==false)" Markdown="false" --- - - + +
@@ -53,165 +35,10 @@ img.stopped{opacity:0.3;}
- + - - - - - - - - - - - - - - getDockerContainers(); - if (!$all_containers) { - $all_containers = []; - echo ""; - } - $info = $DockerTemplates->getAllInfo(); - $contextMenus = []; - - $IP = $eth0['IPADDR:0']; - foreach ($all_containers as $ct) { - $name = $ct['Name']; - $mode = $ct['NetworkMode']; - $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']; - $Support = $ct['Support']; - $Project = $ct['Project']; - - $contextMenus[] = sprintf("addDockerContainerContext('%s', '%s', '%s', %s, %s, %s, '%s', '%s', '%s', '%s');", addslashes($name), addslashes($ct['ImageId']), addslashes($info[$name]['template']), $running, $updateStatus, $is_autostart, addslashes(html_entity_decode($webGuiUrl)), $ct["Id"], addslashes(html_entity_decode($info[$name]['Support'])),addslashes(html_entity_decode($info[$name]['Project']))); - $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 = []; - if ($mode == 'bridge') { - $binds = explode('|',exec("docker inspect --format='{{range \$p,\$c := .HostConfig.PortBindings}}{{\$p}}:{{(index \$c 0).HostPort}}|{{end}}' $name 2>/dev/null")); - $ip = exec("docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $name 2>/dev/null"); - foreach ($binds as $bind) { - if (!$bind) continue; - list($container_port,$host_port) = explode(':',$bind); - $ports[] = sprintf('%s:%s%s:%s', $ip, $container_port, $IP, $host_port); - } - } else { - $binds = explode('|',exec("docker inspect --format='{{range \$p,\$c := .Config.ExposedPorts}}{{\$p}}|{{end}}' $name 2>/dev/null")); - $ip = exec("docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $name 2>/dev/null") ?: $IP; - foreach ($binds as $bind) { - if (!$bind) continue; - $ports[] = sprintf('%s:%s%s:%s', $ip, $bind, $ip, str_replace(['/tcp','/udp'],'',$bind)); - } - } - - $paths = []; - $mounts = explode('|',exec("docker inspect --format='{{range \$c := .HostConfig.Binds}}{{\$c}}|{{end}}' $name 2>/dev/null")); - foreach ($mounts as $mount) { - if (!$mount) continue; - list($host_path,$container_path,$access_mode) = explode(':',$mount); - $paths[] = sprintf('%s%s', htmlspecialchars($container_path), $access_mode=='ro'?'long-arrow-left':'arrows-h', htmlspecialchars($host_path)); - } - ?> - - - - - - - - - - - - - - getDockerImages() as $image) { - if (count($image['usedBy'])) { - continue; - } - - $contextMenus[] = sprintf("addDockerImageContext('%s', '%s');", $image['Id'], implode(', ', $image['Tags'])); - - ?> - - - - - - - - - - - + +
 ApplicationVersionNetworkPort Mappings (App to Host)Volume Mappings (App to Host)AutostartLog
No Docker Containers Installed
- -
- - -
- "; - - ?> -
- - - - - -
Container ID:
- -
- -
By: - - - - - -
-
- update ready"; - } elseif ($updateStatus == "true") { - echo " up-to-date"; - echo ""; - } else { - echo " not available"; - echo ""; - } - ?> - ", $ports)?>", $paths)?>>
Created
- -
- -
- "; - - ?> -
- (orphan image) -
Image ID:
- -
", array_map('htmlspecialchars',$image['Tags']))?>
- -
    
Created
ApplicationVersionNetworkPort Mappings (App to Host)Volume Mappings (App to Host)AutostartLog
Please wait... retrieving container information
@@ -232,48 +59,34 @@ function resize(bind) { } } -$(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 }); - }); - +function loadlist() { + $.get('/plugins/dynamix.docker.manager/include/DockerContainers.php',function(d) { + var data = d.split(/\0/); + $('#docker_list').html(data[0]); + $('head').append(' diff --git a/plugins/dynamix.docker.manager/include/DockerContainers.php b/plugins/dynamix.docker.manager/include/DockerContainers.php new file mode 100644 index 000000000..ef0b85b34 --- /dev/null +++ b/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -0,0 +1,126 @@ + +getDockerContainers(); +if (!$all_containers) { + echo "No Docker containers installed"; + return; +} + +// Read network settings +extract(parse_ini_file('state/network.ini',true)); + +// Read container info +$all = $DockerTemplates->getAllInfo(); +$menu = []; + +foreach ($all_containers as $ct) { + $name = $ct['Name']; + $info = &$all[$name]; + $mode = $ct['NetworkMode']; + $id = $ct['Id']; + $imageID = $ct['ImageId']; + $is_autostart = $info['autostart'] ? 'true':'false'; + $updateStatus = $info['updated']=='true'||$info['updated']=='undef' ? 'true':'false'; + $running = $ct['Running'] ? 'true':'false'; + $template = $info['template']; + $webGui = html_entity_decode($info['url']); + $support = html_entity_decode($info['Support']); + $project = html_entity_decode($info['Project']); + $menu[] = sprintf("addDockerContainerContext('%s','%s','%s',%s,%s,%s,'%s','%s','%s','%s');",addslashes($name),addslashes($imageID),addslashes($template),$running,$updateStatus,$is_autostart,addslashes($webGui),$id,addslashes($support),addslashes($project)); + $shape = $ct['Running'] ? 'play':'square'; + $status = $ct['Running'] ? 'started':'stopped'; + $icon = $info['icon'] ?: '/plugins/dynamix.docker.manager/images/question.png'; + $ports = []; + if ($mode=='bridge') { + $binds = explode('|',exec("docker inspect --format='{{range \$p,\$c := .HostConfig.PortBindings}}{{\$p}}:{{(index \$c 0).HostPort}}|{{end}}' $name 2>/dev/null")); + $ip = exec("docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $name 2>/dev/null"); + foreach ($binds as $bind) { + if (!$bind) continue; + list($container_port,$host_port) = explode(':',$bind); + $ports[] = sprintf('%s:%s%s:%s',$ip, $container_port, $eth0['IPADDR:0'], $host_port); + } + } else { + $binds = explode('|',exec("docker inspect --format='{{range \$p,\$c := .Config.ExposedPorts}}{{\$p}}|{{end}}' $name 2>/dev/null")); + $ip = exec("docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $name 2>/dev/null") ?: $eth0['IPADDR:0']; + foreach ($binds as $bind) { + if (!$bind) continue; + $ports[] = sprintf('%s:%s%s:%s',$ip, $bind, $ip, str_replace(['/tcp','/udp'],'',$bind)); + } + } + $paths = []; + $mounts = explode('|',exec("docker inspect --format='{{range \$c := .HostConfig.Binds}}{{\$c}}|{{end}}' $name 2>/dev/null")); + foreach ($mounts as $mount) { + if (!$mount) continue; + list($host_path,$container_path,$access_mode) = explode(':',$mount); + $paths[] = sprintf('%s%s', htmlspecialchars($container_path), $access_mode=='ro'?'long-arrow-left':'arrows-h', htmlspecialchars($host_path)); + } + echo ""; + echo "
"; + echo ""; + echo "
"; + echo ""; + if ($template) { + echo "".htmlspecialchars($name).""; + } else { + echo htmlspecialchars($name); + } + echo "
Container ID: ".htmlspecialchars($id)."
"; + if ($ct['BaseImage']) echo "
".htmlspecialchars(${ct['BaseImage']})."
"; + echo "
By:"; + $registry = $info['registry']; + if ($registry) { + echo "".htmlspecialchars($ct['Image']).""; + } else { + echo htmlspecialchars($ct['Image']); + } + echo "
"; + if ($updateStatus=='false') { + echo " update ready"; + } elseif ($updateStatus=='true') { + echo " up-to-date"; + echo "
force update
"; + } else { + echo " not available"; + echo "
force update
"; + } + echo "$mode"; + echo "".implode('
',$ports).""; + echo "".implode('
',$paths).""; + echo ""; + echo "
".htmlspecialchars(str_replace('Up','Uptime',$ct['Status']))."
Created ".htmlspecialchars($ct['Created'])."
"; +} +foreach ($DockerClient->getDockerImages() as $image) { + if (count($image['usedBy'])) continue; + $menu[] = sprintf("addDockerImageContext('%s','%s');",$image['Id'],implode(', ',$image['Tags'])); + echo ""; + echo "
"; + echo "
"; + echo ""; + echo "
"; + echo "(orphan image)
Image ID: ".htmlspecialchars($image['Id'])."
"; + if (strpos(implode($image['Tags']),"<none>:<none>")===false) echo "
".implode('
',array_map('htmlspecialchars',$image['Tags']))."
"; + echo "    "; + echo "
Created ".htmlspecialchars($image['Created'])."
"; +} +echo "\0".implode($menu); +?> diff --git a/plugins/dynamix.docker.manager/javascript/docker.js b/plugins/dynamix.docker.manager/javascript/docker.js index 01661d0ec..b7af0bddf 100644 --- a/plugins/dynamix.docker.manager/javascript/docker.js +++ b/plugins/dynamix.docker.manager/javascript/docker.js @@ -1,43 +1,43 @@ var eventURL = "/plugins/dynamix.docker.manager/include/Events.php"; function addDockerContainerContext(container, image, template, started, update, autostart, webui, id, Support, Project) { - var opts = [{header: container, image: "/plugins/dynamix.docker.manager/images/dynamix.docker.manager.png"}]; + var opts = [{header:container, image:"/plugins/dynamix.docker.manager/images/dynamix.docker.manager.png"}]; if (started && (webui !== "" && webui != "#")) { - opts.push({text: 'WebUI', icon: 'fa-globe', href: webui, target: '_blank'}); - opts.push({divider: true}); + opts.push({text:'WebUI', icon:'fa-globe', href:webui, target:'_blank'}); + opts.push({divider:true}); } if (!update) { - opts.push({text: 'Update', icon: 'fa-arrow-down', action: function(e){ e.preventDefault(); execUpContainer(container); }}); - opts.push({divider: true}); + opts.push({text:'Update', icon:'fa-arrow-down', action:function(e){e.preventDefault(); execUpContainer(container);}}); + opts.push({divider:true}); } if (started) { - opts.push({text: 'Stop', icon: 'fa-stop', action: function(e){ e.preventDefault(); eventControl({action: "stop", container: id}); }}); - opts.push({text: 'Restart', icon: 'fa-refresh', action: function(e){ e.preventDefault(); eventControl({action: "restart", container: id}); }}); + opts.push({text:'Stop', icon:'fa-stop', action:function(e){e.preventDefault(); eventControl({action:"stop", container:id}, 'loadlist');}}); + opts.push({text:'Restart', icon:'fa-refresh', action:function(e){e.preventDefault(); eventControl({action:"restart", container:id});}}); } else { - opts.push({text: 'Start', icon: 'fa-play', action: function(e){ e.preventDefault(); eventControl({action: "start", container: id}); }}); + opts.push({text:'Start', icon:'fa-play', action:function(e){e.preventDefault(); eventControl({action:"start", container:id}, 'loadlist');}}); } - opts.push({divider: true}); + opts.push({divider:true}); if (location.pathname.indexOf("/Dashboard") === 0) { - opts.push({text: 'Logs', icon: 'fa-navicon', action: function(e){ e.preventDefault(); containerLogs(container, id); }}); + opts.push({text:'Logs', icon:'fa-navicon', action:function(e){e.preventDefault(); containerLogs(container, id);}}); } if (template) { - opts.push({text: 'Edit', icon: 'fa-wrench', action: function(e){ e.preventDefault(); editContainer(container, template); }}); + opts.push({text:'Edit', icon:'fa-wrench', action:function(e){e.preventDefault(); editContainer(container, template);}}); } - opts.push({divider: true}); - opts.push({text: 'Remove', icon: 'fa-trash', action: function(e){ e.preventDefault(); rmContainer(container, image, id); }}); - if (Support) { - opts.push({divider: true}); - opts.push({text: 'Support', icon: 'fa-question', href: Support, target: '_blank'}); - } - if (Project) { - opts.push({text: 'Project Page', icon: 'fa-life-ring', href: Project, target: '_blank'}); - } - context.attach('#context-'+container, opts); + opts.push({divider:true}); + opts.push({text:'Remove', icon:'fa-trash', action:function(e){e.preventDefault(); rmContainer(container, image, id);}}); + if (Support) { + opts.push({divider:true}); + opts.push({text:'Support', icon:'fa-question', href:Support, target:'_blank'}); + } + if (Project) { + opts.push({text:'Project Page', icon:'fa-life-ring', href:Project, target:'_blank'}); + } + context.attach('#'+id, opts); } function addDockerImageContext(image, imageTag) { - var opts = [{header: '(orphan image)'}]; - opts.push({text: "Remove", icon: "fa-trash", action: function(e){ e.preventDefault(); rmImage(image, imageTag); }}); + var opts = [{header:'(orphan image)'}]; + opts.push({text:"Remove", icon:"fa-trash", action:function(e){e.preventDefault(); rmImage(image, imageTag);}}); context.attach('#context-'+image, opts); } @@ -52,19 +52,19 @@ function popupWithIframe(title, cmd, reload) { $("#iframe-popup").html(''); $("#iframe-popup").dialog({ - autoOpen: true, - title: title, - draggable: true, - width: 800, - height: ((screen.height / 5) * 4) || 0, - resizable: true, - modal: true, - show: {effect: "fade", duration: 250}, - hide: {effect: "fade", duration: 250}, - open: function(ev, ui) { + autoOpen:true, + title:title, + draggable:true, + width:800, + height:((screen.height / 5) * 4) || 0, + resizable:true, + modal:true, + show:{effect:"fade", duration:250}, + hide:{effect:"fade", duration:250}, + open:function(ev, ui) { $("#myIframe").attr("src", cmd); }, - close: function(event, ui) { + close:function(event, ui) { if (reload && !$("#myIframe").contents().find("#canvas").length) { location = window.location.href; } else { @@ -75,7 +75,7 @@ function popupWithIframe(title, cmd, reload) { $(".ui-dialog .ui-dialog-titlebar").addClass("menu"); $(".ui-dialog .ui-dialog-title").css("text-align", "center").css("width", "100%"); $(".ui-dialog .ui-dialog-content").css("padding", "0"); - //$('.ui-widget-overlay').click(function() { $("#iframe-popup").dialog("close"); }); +//$('.ui-widget-overlay').click(function() {$("#iframe-popup").dialog("close");}); } function addContainer() { @@ -98,35 +98,35 @@ function updateContainer(container) { var body = "Update container: "+container; swal({ - title: "Are you sure?", - text: body, - type: "warning", - showCancelButton: true, - confirmButtonColor: "#8CD4F5", - confirmButtonText: "Yes, update it!" + title:"Are you sure?", + text:body, + type:"warning", + showCancelButton:true, + confirmButtonColor:"#8CD4F5", + confirmButtonText:"Yes, update it!" }, function() { execUpContainer(container); }); } function rmContainer(container, image, id) { - var body = "Remove container: "+container+"

"; + var body = "Remove container: "+container+"

"; swal({ - title: "Are you sure?", - text: body, - type: "warning", - html: true, - showCancelButton: true, - confirmButtonColor: "#DD6B55", - confirmButtonText: "Yes, delete it!", - closeOnConfirm: false, - showLoaderOnConfirm: true + title:"Are you sure?", + text:body, + type:"warning", + html:true, + showCancelButton:true, + confirmButtonColor:"#DD6B55", + confirmButtonText:"Yes, delete it!", + closeOnConfirm:false, + showLoaderOnConfirm:true }, function() { if ($("#removeimagechk").prop('checked')) { - eventControl({action: "remove_all", container: id, image: image}); + eventControl({action:"remove_all", container:id, image:image}); } else { - eventControl({action: "remove_container", container: id}); + eventControl({action:"remove_container", container:id}); } }); } @@ -135,26 +135,27 @@ function rmImage(image, imageName) { var body = "Remove image: "+$('