diff --git a/app/Actions/Docker/DeleteAllDanglingServerDockerImages.php b/app/Actions/Docker/DeleteAllDanglingServerDockerImages.php new file mode 100644 index 000000000..592241b95 --- /dev/null +++ b/app/Actions/Docker/DeleteAllDanglingServerDockerImages.php @@ -0,0 +1,15 @@ + 'Invalid JSON returned from Docker inspect', 'raw_output' => $imageDetailsRaw]; + } + + $containerCountRaw = instant_remote_process(["docker ps -q --filter ancestor={$imageId} | wc -l"], $server); + $containerCount = intval(trim($containerCountRaw)); // Convert to an integer + + $imageDetails[0]['ContainerCount'] = $containerCount; + + return $imageDetails; + } +} diff --git a/app/Actions/Docker/ListServerDockerImages.php b/app/Actions/Docker/ListServerDockerImages.php index eaa53871b..ff693b912 100644 --- a/app/Actions/Docker/ListServerDockerImages.php +++ b/app/Actions/Docker/ListServerDockerImages.php @@ -13,25 +13,6 @@ class ListServerDockerImages public static function run($server) { - - $jsonString = instant_remote_process(["docker images --format '{{json .}}'"], $server); - - return collect(explode("\n", trim($jsonString))) - ->filter() - ->map(function ($line) { - $data = json_decode($line, true); - if (!$data) return null; - - return [ - 'tag' => $data['Tag'] ?? '', - 'id' => $data['ID'] ?? '', - 'created_at' => $data['CreatedAt'] ?? '', - 'size' => $data['Size'] ?? '', - 'name' => $data['Repository'] ?? '', - ]; - }) - ->filter() - ->values() - ->toArray(); + return format_docker_command_output_to_json(instant_remote_process(["docker images --format '{{json .}}'"], $server)); } } diff --git a/app/Http/Controllers/Api/DockerController.php b/app/Http/Controllers/Api/DockerController.php index b6e9dc4a9..f42a5a115 100644 --- a/app/Http/Controllers/Api/DockerController.php +++ b/app/Http/Controllers/Api/DockerController.php @@ -2,6 +2,8 @@ namespace App\Http\Controllers\Api; +use App\Actions\Docker\DeleteAllDanglingServerDockerImages; +use App\Actions\Docker\GetServerDockerImageDetails; use App\Actions\Docker\ListServerDockerImages; use App\Http\Controllers\Controller; use App\Models\Server; @@ -26,6 +28,44 @@ class DockerController extends Controller return response()->json(['error' => 'server is not reachable.'], 403); } - return response()->json(ListServerDockerImages::run($server)); + return ListServerDockerImages::run($server); + } + + public function get_server_docker_image_details($server_uuid, $id) + { + $query = Server::query(); + + $server = $query->where('uuid', $server_uuid)->first(); + if (!$server) { + return response()->json(['error' => 'server not found'], 404); + } + + $isReachable = (bool) $server->settings->is_reachable; + // If the server is reachable, send the reachable notification if it was sent before + if ($isReachable !== true) { + return response()->json(['error' => 'server is not reachable.'], 403); + } + + return response()->json(GetServerDockerImageDetails::run($server, $id)); + } + + public function delete_all_dangling_server_docker_images($server_uuid) + { + $query = Server::query(); + + $server = $query->where('uuid', $server_uuid)->first(); + if (!$server) { + return response()->json(['error' => 'server not found'], 404); + } + + $isReachable = (bool) $server->settings->is_reachable; + // If the server is reachable, send the reachable notification if it was sent before + if ($isReachable !== true) { + return response()->json(['error' => 'server is not reachable.'], 403); + } + + $message = DeleteAllDanglingServerDockerImages::run($server); + + return response()->json(['message' => $message]); } } diff --git a/routes/api.php b/routes/api.php index 0fa488689..fc24abcc7 100644 --- a/routes/api.php +++ b/routes/api.php @@ -130,10 +130,13 @@ Route::group([ Route::match(['get', 'post'], '/services/{uuid}/restart', [ServicesController::class, 'action_restart'])->middleware([IgnoreReadOnlyApiToken::class]); Route::match(['get', 'post'], '/services/{uuid}/stop', [ServicesController::class, 'action_stop'])->middleware([IgnoreReadOnlyApiToken::class]); - Route::get('/docker/images/{server_uuid}', [DockerController::class, 'list_server_docker_images']); + Route::get('/docker/{server_uuid}/images', [DockerController::class, 'list_server_docker_images']); + Route::get('/docker/{server_uuid}/image/{id}', [DockerController::class, 'get_server_docker_image_details']); + Route::delete('/docker/{server_uuid}/images/delete/dangling', [DockerController::class, 'delete_all_dangling_server_docker_images']); }); + Route::group([ 'prefix' => 'v1', ], function () {