mirror of
https://github.com/nextcloud/all-in-one.git
synced 2026-05-21 02:40:09 +00:00
aio-interface: offer system prune button (#7677)
This commit is contained in:
@@ -70,6 +70,7 @@ $app->post('/api/docker/backup-check-repair', AIO\Controller\DockerController::c
|
||||
$app->post('/api/docker/backup-test', AIO\Controller\DockerController::class . ':StartBackupContainerTest');
|
||||
$app->post('/api/docker/restore', AIO\Controller\DockerController::class . ':StartBackupContainerRestore');
|
||||
$app->post('/api/docker/stop', AIO\Controller\DockerController::class . ':StopContainer');
|
||||
$app->post('/api/docker/prune', AIO\Controller\DockerController::class . ':SystemPrune');
|
||||
$app->get('/api/docker/logs', AIO\Controller\DockerController::class . ':GetLogs');
|
||||
$app->post('/api/auth/login', AIO\Controller\LoginController::class . ':TryLogin');
|
||||
$app->get('/api/auth/getlogin', AIO\Controller\LoginController::class . ':GetTryLogin');
|
||||
|
||||
@@ -328,6 +328,22 @@ readonly class DockerController {
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function SystemPrune(Request $request, Response $response, array $args) : Response {
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
|
||||
$body = $nonbufResp->getBody();
|
||||
$addToStreamingResponseBody = function (string $message) use ($body) : void {
|
||||
$body->write("<div>$message</div>");
|
||||
};
|
||||
|
||||
$this->dockerActionManager->SystemPrune($addToStreamingResponseBody);
|
||||
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function stopTopContainer() : void {
|
||||
$id = self::TOP_CONTAINER;
|
||||
$this->PerformRecursiveContainerStop($id);
|
||||
|
||||
@@ -997,4 +997,71 @@ readonly class DockerActionManager {
|
||||
return $this->dockerHubManager->GetLatestDigestOfTag($imageName, $tag);
|
||||
}
|
||||
}
|
||||
|
||||
public function SystemPrune(?\Closure $addToStreamingResponseBody = null): void {
|
||||
$endpoints = [
|
||||
// Remove stopped containers
|
||||
'containers/prune',
|
||||
// Remove unused images
|
||||
'images/prune',
|
||||
// Remove unused volumes
|
||||
'volumes/prune',
|
||||
// Remove unused networks
|
||||
'networks/prune',
|
||||
// Prune build cache
|
||||
'build/prune',
|
||||
];
|
||||
|
||||
foreach ($endpoints as $endpoint) {
|
||||
// Special-case images prune to include the dangling filter as requested
|
||||
if ($endpoint === 'images/prune') {
|
||||
$filters = json_encode(['dangling' => ['false']]);
|
||||
$url = $this->BuildApiUrl($endpoint . '?filters=' . urlencode((string) $filters));
|
||||
} else {
|
||||
$url = $this->BuildApiUrl($endpoint);
|
||||
}
|
||||
|
||||
if ($addToStreamingResponseBody !== null) {
|
||||
$addToStreamingResponseBody("Running $endpoint...");
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->guzzleClient->post($url);
|
||||
if ($addToStreamingResponseBody !== null) {
|
||||
$data = json_decode((string)$response->getBody(), true);
|
||||
$deleted = 0;
|
||||
foreach (['ContainersDeleted', 'ImagesDeleted', 'VolumesDeleted', 'NetworksDeleted', 'CachesDeleted'] as $key) {
|
||||
if (isset($data[$key]) && is_array($data[$key])) {
|
||||
$deleted += count($data[$key]);
|
||||
}
|
||||
}
|
||||
$reclaimed = $data['SpaceReclaimed'] ?? 0;
|
||||
$parts = [];
|
||||
if ($deleted > 0) {
|
||||
$parts[] = "$deleted item(s) deleted";
|
||||
}
|
||||
if ($reclaimed > 0) {
|
||||
$i = (int)floor(log($reclaimed, 1024));
|
||||
$parts[] = 'Space reclaimed: ' . (string)round($reclaimed / (1024 ** $i), 2) . ' ' . ['B','KB','MB','GB'][$i];
|
||||
}
|
||||
$addToStreamingResponseBody(!empty($parts) ? implode('. ', $parts) . '.' : 'Nothing to prune.');
|
||||
}
|
||||
} catch (RequestException $e) {
|
||||
error_log(sprintf('Docker prune (%s) failed: %s', $endpoint, $e->getMessage()));
|
||||
if ($addToStreamingResponseBody !== null) {
|
||||
$addToStreamingResponseBody('Error: ' . $e->getMessage());
|
||||
}
|
||||
// continue with next prune step
|
||||
}
|
||||
}
|
||||
|
||||
if ($addToStreamingResponseBody !== null) {
|
||||
$addToStreamingResponseBody("Docker system prune completed.");
|
||||
sleep(1);
|
||||
|
||||
// We automatically reload after 10s so that the output can be read or copied if necessary
|
||||
$addToStreamingResponseBody("Automatically reloading the page after 10s.");
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,6 +582,18 @@
|
||||
|
||||
{% if is_backup_container_running == false %}
|
||||
{% if isApacheStarting == false %}
|
||||
{% if isAnyRunning == true %}
|
||||
<h2>Docker System Prune</h2>
|
||||
<details>
|
||||
<summary>Click here to reveal a button to prune the docker system.</summary>
|
||||
<p>By clicking the button below you can run "docker system prune -a". This will remove unused images, containers, networks, volumes and build cache. It will not delete data of running containers.</p>
|
||||
<form method="POST" action="api/docker/prune" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Prune docker system" data-confirm="Run docker system prune -a? This will remove unused images, containers, networks, volumes and build cache. It will not delete data of running containers. Continue?" />
|
||||
</form>
|
||||
</details>
|
||||
{% endif %}
|
||||
<h2>AIO passphrase change</h2>
|
||||
<details>
|
||||
<summary>Click here to change your AIO passphrase</summary>
|
||||
|
||||
Reference in New Issue
Block a user