diff --git a/docker/command.cgi b/docker/command.cgi
index d752bc0..b40f354 100644
--- a/docker/command.cgi
+++ b/docker/command.cgi
@@ -1,25 +1,30 @@
#!/usr/bin/perl
+use strict;
+use warnings;
require './docker-lib.pl';
-ui_print_header(undef, &text('index_title'), "", undef, 1, 1);
+#ui_print_header(undef, &text('index_title'), "", undef, 1, 1);
&ReadParse();
-&error_setup($text{'command_err'});
+&error_setup(text('command_err'));
-$command = $in{'c'};
+our (%in);
+my $command = $in{'c'};
+
+my $err;
if ($command == 'start') {
- start_container($in{'container'});
+ $err = container_command($in{'container'}, 'start');
}
if ($command == 'stop') {
- stop_container($in{'container'});
+ $err = container_command($in{'container'}, 'stop');
}
if ($command == 'restart') {
- restart_container($in{'container'})
+ $err = container_command($in{'container'}, 'restart')
}
-#&error($err) if ($err);
+&error($err) if ($err);
&webmin_log(ucfirst($command), 'docker container', $in{'container'});
&redirect("");
\ No newline at end of file
diff --git a/docker/container.cgi b/docker/container.cgi
new file mode 100644
index 0000000..4500ac0
--- /dev/null
+++ b/docker/container.cgi
@@ -0,0 +1,53 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Data::Dumper;
+
+require './docker-lib.pl';
+&ReadParse();
+
+our (%in);
+
+my $container = $in{'container'};
+my $tab = $in{'tab'};
+
+ui_print_header(undef, text('view_container_title', $container), "", undef, undef, $in{'nonavlinks'});
+
+
+my @tabs = ( [ 'log', &text('tab_log') ],
+ [ 'inspect', &text('tab_inspect') ] );
+
+print ui_tabs_start(\@tabs, 'log', $tab, 1);
+
+# LOGS TAB
+print ui_tabs_start_tab('mode', 'log');
+my ($failed, $result) = container_logs($container);
+if ($failed) {
+ print ui_alert_box($failed, 'danger');
+} else {
+ print &ui_form_start("container.cgi");
+ print &ui_hidden("container", $container),"\n";
+ print &ui_hidden("tab", "log"),"\n";
+ print &ui_submit(text('label_refresh'));
+ print &ui_form_end(),"
\n";
+
+ print "
" . $result . ""; +} +print ui_tabs_end_tab('mode', 'log'); + +# INSPECT TAB +print ui_tabs_start_tab('mode', 'inspect'); +my ($failedB, $resultB) = inspect_container($container); +if ($failedB) { + print ui_alert_box($failedB, 'danger'); +} else { + print "
" . $resultB . ""; +} +print ui_tabs_end_tab('mode', 'inspect'); + +print ui_tabs_end(); + +&ui_print_footer("", text('index_return')); + +# if using authentic theme, enable codemirror for readability +print ""; diff --git a/docker/docker-lib.pl b/docker/docker-lib.pl index 9302a81..88155a0 100644 --- a/docker/docker-lib.pl +++ b/docker/docker-lib.pl @@ -11,34 +11,49 @@ init_config(); -sub get_status { - my $fail; - my $status = "{}"; - my $code = execute_command('docker info --format "{{json .}}"', undef, \$status, \$fail, 0, 1); +sub docker_command { + my($command, $format, $safe) = @_; + $format ||= ""; + $safe ||= 1; + + if ($format) { + $format = ' --format "' . $format . '"' + } + + my ($result, $fail); + my $code = execute_command('docker ' . $command . $format, undef, \$result, \$fail, 0, $safe); if ($code != 0) { - return $fail; + return $code, $fail; } - my $json = decode_json($status); - if ($json->{ServerErrors}) { - return $json->{ServerErrors}[0]; + return 0, $result +} + + +sub get_status { + my ($code, $result) = docker_command('info'); + if ($code != 0) { + return $result; } - return 0, $json; + # my $json = decode_json($result); + # if ($json->{ServerErrors}) { + # return $json->{ServerErrors}[0]; + # } + + return 0, $result; } sub get_containers { - my ($containers, $fail); - my $code = execute_command('docker container ls --all --format {{.ID}},{{.Names}},{{.Image}},{{.Status}}', undef, \$containers, \$fail, 0, 1); - + my ($code, $result) = docker_command('container ls --all ', '{{.ID}},{{.Names}},{{.Image}},{{.Status}}'); if ($code != 0) { - return $fail; + return $result; } my @results; - my @containers = split(/\n/, $containers); + my @containers = split(/\n/, $result); foreach my $u (@containers) { my ($id, $name, $image, $status) = split(/,/, $u); push (@results, { @@ -54,15 +69,13 @@ sub get_containers sub get_stats { - my ($containers, $fail); - my $code = execute_command('docker stats --all --no-stream --format "{{.ID}},{{.CPUPerc}},{{.MemPerc}},{{.MemUsage}}"', undef, \$containers, \$fail, 0, 1); - + my ($code, $result) = docker_command('stats --all --no-stream', '{{.ID}},{{.CPUPerc}},{{.MemPerc}},{{.MemUsage}}'); if ($code != 0) { - return $fail; + return $result; } my %results = ( ); - my @containers = split(/\n/, $containers); + my @containers = split(/\n/, $result); foreach my $u (@containers) { my ($id, $cpu, $mem, $memUsage) = split(/,/, $u); @@ -79,56 +92,40 @@ sub get_stats sub inspect_container { my($container) = @_; - my ($result, $fail); - # my $code = execute_command('docker inspect ' . $container . ' --format "{{json .}}"', undef, \$result, \$fail, 0, 1); - my $code = execute_command('docker inspect ' . $container, undef, \$result, \$fail, 0, 1); - + my ($code, $result) = docker_command('inspect ' . $container . ' --type=container --size'); if ($code != 0) { - return $fail; + return $result; } - - # my $json = decode_json($result); - # if ($json->{ServerErrors}) { - # return $json->{ServerErrors}[0]; - # } - - # return 0, $json, $result; + return 0, $result; } sub container_logs { my($container) = @_; - my ($result, $fail); - my $code = execute_command('docker logs ' . $container, undef, \$result, \$fail, 0, 1); - + my ($code, $result) = docker_command('logs ' . $container); if ($code != 0) { - return $fail; + return $result; } return 0, $result; } -sub start_container +sub container_command { - my($container) = @_; - my ($output, $fail); - execute_command('docker start ' . $container, undef, \$output, \$fail, 0, 1); -} + my($container, $command) = @_; -sub stop_container -{ - my($container) = @_; - my ($output, $fail); - execute_command('docker stop ' . $container, undef, \$output, \$fail, 0, 1); -} + if (!($command !~~ ['start', 'stop', 'restart'])) { + return "Command not allowed"; + } + + my ($code, $result) = docker_command($command . ' ' . $container); + if ($code != 0) { + return $result; + } -sub restart_container -{ - my($container) = @_; - my ($output, $fail); - execute_command('docker restart ' . $container, undef, \$output, \$fail, 0, 1); + return $result; } sub circular_grid @@ -136,16 +133,25 @@ sub circular_grid my($statsRaw, $depth) = @_; $depth ||= 1; + print Dumper($statsRaw); + my $result = ui_table_start($depth > 1 ? "" : "Info"); + my @stats; foreach my $field ( keys %{$statsRaw}) { if (ref $statsRaw->{$field} eq ref {}) { # If hash down the rabbit hole we go - push (@stats, sprintf("%s: %s", $field, circular_grid($statsRaw->{$field}, $depth + 1))); + $result = $result . ui_table_hr() . ui_table_span($field); + $result = $result . ui_table_span(circular_grid($statsRaw->{$field}, $depth + 1)); + #push (@stats, sprintf("%s: %s", $field, circular_grid($statsRaw->{$field}, $depth + 1))); } elsif (ref $statsRaw->{$field} eq 'ARRAY') { # Make the brave assumption we can flatten and join the array - push (@stats, sprintf("%s: %s
" . $status . ""; } print ui_tabs_end_tab('mode', 'info'); @@ -34,6 +35,10 @@ my($stat_fail, %stats) = get_stats(); if ($fail) { print ui_alert_box($fail, 'danger'); } else { + print &ui_form_start(""); + print &ui_submit(text('label_refresh')); + print &ui_form_end(),"
" . $result . ""; - -&ui_print_footer("", text('index_return')); - -# if using authentic theme, enable codemirror for readability -print ""; diff --git a/docker/lang/en b/docker/lang/en index 33e586b..f63504a 100644 --- a/docker/lang/en +++ b/docker/lang/en @@ -1,9 +1,14 @@ -index_title=Docker container management not_installed=Docker was not found on this system + +index_title=Docker container management index_return=container list +view_container_title=Container $1 + tab_info=Docker Info tab_containers=Containers +tab_log=Log +tab_inspect=Inspect command_err=Command could not be run diff --git a/docker/logs.cgi b/docker/logs.cgi deleted file mode 100644 index ef0d934..0000000 --- a/docker/logs.cgi +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; -use Data::Dumper; - -require './docker-lib.pl'; -&ReadParse(); - -our (%in); - -my $container = $in{'container'}; - -ui_print_header("".&html_escape($container)."", text('index_title'), "", undef, undef, $in{'nonavlinks'}); - -my ($failed, $result) = container_logs($container); -if ($failed) { - &ui_print_endpage(ui_alert_box($failed, 'danger'), "Back", "/"); -} - -print &ui_form_start("inspect.cgi"); -print &ui_hidden("container", $container),"\n"; -print &ui_submit(text('label_refresh')); -print &ui_form_end(),"
" . Dumper($result) . ""; - -&ui_print_footer("", text('index_return')); - -# if using authentic theme, enable codemirror for readability -print ""; diff --git a/docker/module.info b/docker/module.info index 0c26543..be04e3f 100644 --- a/docker/module.info +++ b/docker/module.info @@ -1,3 +1,4 @@ desc=Docker container management os_support=*-linux -category=servers \ No newline at end of file +category=servers +longdesc=View and perform basic actions on docker containers on the host \ No newline at end of file