Skip to content

Commit

Permalink
Add orphans section
Browse files Browse the repository at this point in the history
Add a way to generate a run or compose for a container
Add most of the code to actually update containers (needs testing)
  • Loading branch information
austinwbest committed Nov 22, 2023
1 parent 3848540 commit 498fb18
Show file tree
Hide file tree
Showing 11 changed files with 375 additions and 22 deletions.
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,18 @@ This is an example, adjust paths and settings for your setup

```
dockwatch:
container_name: dockwatch
image: ghcr.io/notifiarr/dockwatch:main
ports:
- 9999:80/tcp
environment:
- PUID=1001
- PGID=100
- UMASK=022
- TZ=Etc/UTC
volumes:
- /appdata/dockwatch/config:/config
- /var/run/docker.sock:/var/run/docker.sock
container_name: dockwatch
image: ghcr.io/notifiarr/dockwatch:main
ports:
- 9999:80/tcp
environment:
- PUID=1001
- PGID=100
- UMASK=022
- TZ=Etc/UTC
volumes:
- /appdata/dockwatch/config:/config
- /var/run/docker.sock:/var/run/docker.sock
```

### Manual
Expand Down
18 changes: 10 additions & 8 deletions root/app/www/public/ajax/containers.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@
<option value="2">Restart</option>
<option value="3">Stop</option>
<option value="4">Pull</option>
<option value="5">Inspect -> Run</option>
<option value="6">Inspect -> Compose</option>
</select>
<button type="button" class="btn btn-outline-info" onclick="massApplyContainerTrigger()">Apply</button>
</td>
Expand Down Expand Up @@ -206,6 +208,14 @@
setFile(PULL_FILE, $pulls);
$result = 'Pulled ' . $container['Names'] . '<br>';
break;
case '5': //-- GERNERATE RUN
$run = dockerAutoRun($container['Names']);
$result = 'docker run ' . $container['Names'] . '<br><pre>' . $run . '</pre>';
break;
case '6': //-- GENERATE COMPOSE
$run = dockerAutoCompose($container['Names']);
$result = 'compose ' . $container['Names'] . '<br><pre>' . $run . '</pre>';
break;
}

$processList = dockerProcessList(false);
Expand Down Expand Up @@ -300,11 +310,3 @@

echo json_encode($return);
}

if ($_POST['m'] == 'startContainer') {

}

if ($_POST['m'] == 'restartContainer') {

}
2 changes: 1 addition & 1 deletion root/app/www/public/ajax/logs.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,5 @@
} else {
$error = 'Selected log file not found';
}
echo json_encode(['header' => $header, 'log' => $content, 'error' => $error]);
echo json_encode(['header' => $header, 'log' => str_replace('[ERROR]', '<span class="text-danger">[ERROR]</span>', $content), 'error' => $error]);
}
72 changes: 72 additions & 0 deletions root/app/www/public/ajax/orphans.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

/*
----------------------------------
------ Created: 111523 ------
------ Austin Best ------
----------------------------------
*/

require 'shared.php';

if ($_POST['m'] == 'init') {
$orphans = json_decode(dockerGetOrphans(), true);

?>
<div class="container-fluid pt-4 px-4 mb-5">
<div class="bg-secondary rounded h-100 p-4">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col"><input type="checkbox" class="form-check-input" onclick="$('.orphans-check').prop('checked', $(this).prop('checked'));"></th>
<th scope="col">ID</th>
<th scope="col">Created</th>
<th scope="col">Repository</th>
<th scope="col">Size</th>
</tr>
</thead>
<tbody>
<?php
foreach ($orphans as $orphan) {
?>
<tr id="<?= $orphan['ID'] ?>">
<th scope="row"><input id="orphan-<?= $orphan['ID'] ?>" type="checkbox" class="form-check-input orphans-check"></th>
<td><?= $orphan['ID'] ?></td>
<td><?= $orphan['CreatedSince'] ?></td>
<td><?= $orphan['Repository'] ?></td>
<td><?= $orphan['Size'] ?></td>
</tr>
<?php
}
?>
</tbody>
<tfoot>
<tr>
<td colspan="3">
With selected:
<select id="massOrphanTrigger" class="form-control d-inline-block w-50">
<option value="0">-- Select option --</option>
<option value="1">Remove</option>
</select>
<button type="button" class="btn btn-outline-info" onclick="removeOrphans()">Apply</button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<?php
}

if ($_POST['m'] == 'removeOrphans') {
switch ($_POST['trigger']) {
case '1': //-- Remove
$remove = dockerRemoveImage($_POST['orphan']);
if (strpos($remove, 'Error') !== false) {
echo $remove;
}
break;
}
}
44 changes: 44 additions & 0 deletions root/app/www/public/crons/pulls.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
$updateSettings = $settings['containers'];
$states = is_array($state) ? $state : json_decode($state, true);
$pulls = getFile(PULL_FILE);
$notify = [];

if ($updateSettings) {
foreach ($updateSettings as $containerHash => $settings) {
Expand Down Expand Up @@ -75,6 +76,28 @@
'image' => $inspectImage[0]['Id'],
'container' => $inspectContainer[0]['Image']
];

switch ($settings['updates']) {
case 1: //-- Auto update
if ($settings['notifications']['triggers']['updated']['active'] && $inspectImage[0]['Id'] != $inspectContainer[0]['Image']) {
logger($logfile, 'Building run command for ' . $containerState['Names']);
//$runCommand = dockerAutoRun($containerState['Names']);
logger($logfile, 'Stopping container ' . $containerState['Names']);
//dockerStopContainer($containerState['Names']);
logger($logfile, 'Removing container ' . $containerState['Names']);
//dockerRemoveContainer($containerState['Id']);
logger($logfile, 'Updating container ' . $containerState['Names']);
//dockerUpdateContainer($runCommand);

$notify['updated'][] = ['container' => $containerState['Names']];
}
break;
case 2: //-- Check for updates
if ($settings['notifications']['triggers']['updates']['active'] && $inspectImage[0]['Id'] != $inspectContainer[0]['Image']) {
$notify['available'][] = ['container' => $containerState['Names']];
}
break;
}
} else {
$msg = 'Skipping: ' . $containerState['Names'] . ' (\'' . $settings['frequency'] . '\' frequency not met)';
logger($logfile, $msg);
Expand All @@ -89,5 +112,26 @@
}

setFile(PULL_FILE, $pulls);

if ($notify) {
//-- IF THEY USE THE SAME PLATFORM, COMBINE THEM
if ($settings['notifications']['triggers']['updated']['platform'] == $settings['notifications']['triggers']['updates']['platform']) {
$payload = ['event' => 'updates', 'available' => $notify['available'], 'updated' => $notify['updated']];
logger($logfile, 'Notification payload: ' . json_encode($payload));
$notifications->notify($settings['notifications']['triggers']['updated']['platform'], $payload);
} else {
if ($notify['available']) {
$payload = ['event' => 'updates', 'available' => $notify['available']];
logger($logfile, 'Notification payload: ' . json_encode($payload));
$notifications->notify($settings['notifications']['triggers']['updated']['platform'], $payload);
}

if ($notify['usage']['mem']) {
$payload = ['event' => 'updates', 'updated' => $notify['updated']];
logger($logfile, 'Notification payload: ' . json_encode($payload));
$notifications->notify($settings['notifications']['triggers']['updates']['platform'], $payload);
}
}
}
}
logger($logfile, 'Cron run finished');
47 changes: 47 additions & 0 deletions root/app/www/public/functions/docker.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,50 @@ function dockerPullContainer($image)
$cmd = '/usr/bin/docker pull ' . $image;
return shell_exec($cmd . ' 2>&1');
}

function dockerAutoCompose($containerName)
{
$cmd = '/usr/bin/docker run --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/red5d/docker-autocompose ' . $containerName;
$run = shell_exec($cmd . ' 2>&1');
$lines = explode("\n", $run);
$skip = true;
$command = [];
foreach ($lines as $line) {
if (strpos($line, 'networks') !== false) {
$skip = false;
}

if ($skip) {
continue;
}

$command[] = $line;
}

return implode("\n", $command);
}

function dockerAutoRun($containerName)
{
// Smarter people than me... https://gist.github.com/efrecon/8ce9c75d518b6eb863f667442d7bc679
$cmd = '/usr/bin/docker inspect --format "$(cat ' . ABSOLUTE_PATH . 'run.tpl)" ' . $containerName;
return shell_exec($cmd . ' 2>&1');
}

function dockerUpdateContainer($command)
{
$cmd = '/usr/bin/' . $command;
return shell_exec($cmd . ' 2>&1');
}

function dockerGetOrphans()
{
$cmd = '/usr/bin/docker images -f dangling=true --format="{{json . }}" | jq -s --tab .';
return shell_exec($cmd . ' 2>&1');
}

function dockerRemoveImage($id)
{
$cmd = '/usr/bin/docker rmi ' . $id;
return shell_exec($cmd . ' 2>&1');
}
1 change: 1 addition & 0 deletions root/app/www/public/includes/header.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
<div class="navbar-nav w-100">
<a id="menu-overview" onclick="initPage('overview')" style="cursor: pointer;" class="nav-item nav-link active"><i class="fas fa-heartbeat me-2"></i>Overview</a>
<a id="menu-containers" onclick="initPage('containers')" style="cursor: pointer;" class="nav-item nav-link"><i class="fas fa-th me-2"></i>Containers</a>
<a id="menu-orphans" onclick="initPage('orphans')" style="cursor: pointer;" class="nav-item nav-link"><i class="fas fa-th me-2"></i>Orphans</a>
<a id="menu-notification" onclick="initPage('notification')" style="cursor: pointer;" class="nav-item nav-link"><i class="fas fa-comment-dots me-2"></i>Notifications</a>
<a id="menu-settings" onclick="initPage('settings')" style="cursor: pointer;" class="nav-item nav-link"><i class="fas fa-tools me-2"></i>Settings</a>
<a id="menu-logs" onclick="initPage('logs')" style="cursor: pointer;" class="nav-item nav-link"><i class="fas fa-file-code me-2"></i>Logs</a>
Expand Down
1 change: 1 addition & 0 deletions root/app/www/public/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
?>
<div id="content-overview" style="display: none;"></div>
<div id="content-containers" style="display: none;"></div>
<div id="content-orphans" style="display: none;"></div>
<div id="content-notification" style="display: none;"></div>
<div id="content-settings" style="display: none;"></div>
<div id="content-logs" style="display: none;"></div>
Expand Down
2 changes: 1 addition & 1 deletion root/app/www/public/js/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function initPage(page)
data: '&m=init&page=' + page,
success: function (resultData) {
$('#content-' + page).html(resultData);
loadingStop();
setTimeout(loadingStop, 1000);
}
});

Expand Down
37 changes: 37 additions & 0 deletions root/app/www/public/js/orphans.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
function removeOrphans()
{
if ($('#massOrphanTrigger').val() == '0') {
return;
}

loadingStart();

let params = '';
$.each($('[id^=orphan-]'), function () {
if ($(this).prop('checked')) {
const orphan = $(this).attr('id').replace('orphan-', '');

$.ajax({
type: 'POST',
url: '../ajax/orphans.php',
data: '&m=removeOrphans&orphan=' + orphan + '&trigger=' + $('#massOrphanTrigger').val(),
async: 'global',
success: function (resultData) {
$('#massOrphanTrigger').val('0');

if (resultData) {
toast('Orphans', 'Orphan ' + orphan + ' failed to remove. ' + resultData, 'error');
return;
}

toast('Orphans', 'Orphan ' + orphan + ' has been removed', 'success');
$('#' + orphan).remove();
}
});
}
});

$('.orphans-check').prop('checked', false);
loadingStop();
}
// ---------------------------------------------------------------------------------------------
Loading

0 comments on commit 498fb18

Please sign in to comment.