feat: add functionality to delete orphaned containers in maintenance settings

This commit is contained in:
biersoeckli
2025-01-24 16:45:03 +00:00
parent e85f302e31
commit 3370c4d13b
3 changed files with 31 additions and 1 deletions

View File

@@ -1,7 +1,7 @@
'use client';
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { cleanupOldBuildJobs, cleanupOldTmpFiles, purgeRegistryImages, updateRegistry, updateTraefikMeCertificates } from "../server/actions";
import { cleanupOldBuildJobs, cleanupOldTmpFiles, deleteAllFailedAndSuccededPods, purgeRegistryImages, updateRegistry, updateTraefikMeCertificates } from "../server/actions";
import { Button } from "@/components/ui/button";
import { Toast } from "@/frontend/utils/toast.utils";
import { useConfirmDialog } from "@/frontend/states/zustand.states";
@@ -87,6 +87,16 @@ export default function QuickStackMaintenanceSettings({
}
}}><RotateCcw />Update Traefik.me SSL Certificates</Button>
<Button variant="secondary" onClick={async () => {
if (await useConfirm.openConfirmDialog({
title: 'Delete Orphaned Containers',
description: 'This action deletes all unused pods (failed or succeded). Use this action to free up resources.',
okButton: "Delete Orphaned Containers"
})) {
Toast.fromAction(() => deleteAllFailedAndSuccededPods());
}
}}><Trash /> Delete Orphaned Containers</Button>
</CardContent>
</Card>
</div>;

View File

@@ -16,6 +16,7 @@ import buildService from "@/server/services/build.service";
import { PathUtils } from "@/server/utils/path.utils";
import { FsUtils } from "@/server/utils/fs.utils";
import traefikMeDomainStandaloneService from "@/server/services/standalone-services/traefik-me-domain-standalone.service";
import standalonePodService from "@/server/services/standalone-services/standalone-pod.service";
export const updateIngressSettings = async (prevState: any, inputData: QsIngressSettingsModel) =>
saveFormAction(inputData, qsIngressSettingsZodModel, async (validatedData) => {
@@ -119,6 +120,13 @@ export const updateTraefikMeCertificates = async () =>
return new SuccessActionResult(undefined, 'Certificates will be updated, this might take a few seconds.');
});
export const deleteAllFailedAndSuccededPods = async () =>
simpleAction(async () => {
await getAuthUserSession();
await standalonePodService.deleteAllFailedAndSuccededPods();
return new SuccessActionResult(undefined, 'Successfully deleted all failed and succeeded pods.');
});
export const purgeRegistryImages = async () =>
simpleAction(async () => {
await getAuthUserSession();

View File

@@ -2,6 +2,7 @@ import k3s from "../../adapter/kubernetes-api.adapter";
import fs from 'fs';
import stream from 'stream';
import * as k8s from '@kubernetes/client-node';
import dataAccess from "../../../server/adapter/db.client";
class SetupPodService {
@@ -226,7 +227,18 @@ class SetupPodService {
}, 5000);
});
});
}
async deleteAllFailedAndSuccededPods() {
const projects = await dataAccess.client.project.findMany();
for (const project of projects) {
const podsOfNamespace = await k3s.core.listNamespacedPod(project.id);
const failedPods = podsOfNamespace.body.items.filter((pod) => ['Failed', 'Succeeded'].includes(pod.status?.phase!));
for (const pod of failedPods) {
await k3s.core.deleteNamespacedPod(pod.metadata?.name!, project.id);
}
}
}
}