From 683b8c966fa8d94e568d75fd96f8255b50c91af2 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 28 Sep 2022 15:41:20 +0200 Subject: [PATCH] feat: cleanup unconfigured services and databases --- apps/api/src/lib/services/handlers.ts | 4 +- .../routes/api/v1/applications/handlers.ts | 4 +- .../src/routes/api/v1/applications/index.ts | 4 +- .../src/routes/api/v1/databases/handlers.ts | 24 ++++++++ apps/api/src/routes/api/v1/databases/index.ts | 4 +- apps/api/src/routes/api/v1/handlers.ts | 16 ++++- .../src/routes/api/v1/services/handlers.ts | 27 +++++++++ apps/api/src/routes/api/v1/services/index.ts | 3 + .../src/routes/databases/[id]/__layout.svelte | 1 - apps/ui/src/routes/index.svelte | 58 +++++++++++++++++-- 10 files changed, 130 insertions(+), 15 deletions(-) diff --git a/apps/api/src/lib/services/handlers.ts b/apps/api/src/lib/services/handlers.ts index e951004fa..ee9ab88ec 100644 --- a/apps/api/src/lib/services/handlers.ts +++ b/apps/api/src/lib/services/handlers.ts @@ -1883,11 +1883,11 @@ async function stopServiceContainers(request: FastifyRequest) if (destinationDockerId) { await executeDockerCmd({ dockerId: destinationDockerId, - command: `docker ps -a --filter 'label=com.docker.compose.project=${id}' --format {{.ID}}|xargs -n 1 docker stop -t 0` + command: `docker ps -a --filter 'label=com.docker.compose.project=${id}' --format {{.ID}}|xargs -r -n 1 docker stop -t 0` }) await executeDockerCmd({ dockerId: destinationDockerId, - command: `docker ps -a --filter 'label=com.docker.compose.project=${id}' --format {{.ID}}|xargs -n 1 docker rm --force` + command: `docker ps -a --filter 'label=com.docker.compose.project=${id}' --format {{.ID}}|xargs -r -n 1 docker rm --force` }) return {} } diff --git a/apps/api/src/routes/api/v1/applications/handlers.ts b/apps/api/src/routes/api/v1/applications/handlers.ts index 895f69dc5..fb5ea386c 100644 --- a/apps/api/src/routes/api/v1/applications/handlers.ts +++ b/apps/api/src/routes/api/v1/applications/handlers.ts @@ -69,9 +69,9 @@ export async function getImages(request: FastifyRequest) { return errorHandler({ status, message }) } } -export async function cleanupUnconfigured(request: FastifyRequest) { +export async function cleanupUnconfiguredApplications(request: FastifyRequest) { try { - let teamId = request.user.teamId + const teamId = request.user.teamId let applications = await prisma.application.findMany({ where: { teams: { some: { id: teamId === "0" ? undefined : teamId } } }, include: { settings: true, destinationDocker: true, teams: true }, diff --git a/apps/api/src/routes/api/v1/applications/index.ts b/apps/api/src/routes/api/v1/applications/index.ts index cece28f84..26e7ff16a 100644 --- a/apps/api/src/routes/api/v1/applications/index.ts +++ b/apps/api/src/routes/api/v1/applications/index.ts @@ -1,6 +1,6 @@ import { FastifyPluginAsync } from 'fastify'; import { OnlyId } from '../../../../types'; -import { cancelDeployment, checkDNS, checkDomain, checkRepository, cleanupUnconfigured, deleteApplication, deleteSecret, deleteStorage, deployApplication, getApplication, getApplicationLogs, getApplicationStatus, getBuildIdLogs, getBuildPack, getBuilds, getGitHubToken, getGitLabSSHKey, getImages, getPreviews, getPreviewStatus, getSecrets, getStorages, getUsage, listApplications, loadPreviews, newApplication, restartApplication, restartPreview, saveApplication, saveApplicationSettings, saveApplicationSource, saveBuildPack, saveConnectedDatabase, saveDeployKey, saveDestination, saveGitLabSSHKey, saveRepository, saveSecret, saveStorage, stopApplication, stopPreviewApplication, updatePreviewSecret, updateSecret } from './handlers'; +import { cancelDeployment, checkDNS, checkDomain, checkRepository, cleanupUnconfiguredApplications, deleteApplication, deleteSecret, deleteStorage, deployApplication, getApplication, getApplicationLogs, getApplicationStatus, getBuildIdLogs, getBuildPack, getBuilds, getGitHubToken, getGitLabSSHKey, getImages, getPreviews, getPreviewStatus, getSecrets, getStorages, getUsage, listApplications, loadPreviews, newApplication, restartApplication, restartPreview, saveApplication, saveApplicationSettings, saveApplicationSource, saveBuildPack, saveConnectedDatabase, saveDeployKey, saveDestination, saveGitLabSSHKey, saveRepository, saveSecret, saveStorage, stopApplication, stopPreviewApplication, updatePreviewSecret, updateSecret } from './handlers'; import type { CancelDeployment, CheckDNS, CheckDomain, CheckRepository, DeleteApplication, DeleteSecret, DeleteStorage, DeployApplication, GetApplicationLogs, GetBuildIdLogs, GetBuilds, GetImages, RestartPreviewApplication, SaveApplication, SaveApplicationSettings, SaveApplicationSource, SaveDeployKey, SaveDestination, SaveSecret, SaveStorage, StopPreviewApplication } from './types'; @@ -11,7 +11,7 @@ const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get('/', async (request) => await listApplications(request)); fastify.post('/images', async (request) => await getImages(request)); - fastify.post('/cleanup/unconfigured', async (request) => await cleanupUnconfigured(request)); + fastify.post('/cleanup/unconfigured', async (request) => await cleanupUnconfiguredApplications(request)); fastify.post('/new', async (request, reply) => await newApplication(request, reply)); diff --git a/apps/api/src/routes/api/v1/databases/handlers.ts b/apps/api/src/routes/api/v1/databases/handlers.ts index 16d43205c..48a29a900 100644 --- a/apps/api/src/routes/api/v1/databases/handlers.ts +++ b/apps/api/src/routes/api/v1/databases/handlers.ts @@ -51,6 +51,30 @@ export async function newDatabase(request: FastifyRequest, reply: FastifyReply) return errorHandler({ status, message }) } } +export async function cleanupUnconfiguredDatabases(request: FastifyRequest) { + try { + const teamId = request.user.teamId; + let databases = await prisma.database.findMany({ + where: { teams: { some: { id: teamId === "0" ? undefined : teamId } } }, + include: { settings: true, destinationDocker: true, teams: true }, + }); + for (const database of databases) { + if (!database?.version) { + const { id } = database; + if (database.destinationDockerId) { + const everStarted = await stopDatabaseContainer(database); + if (everStarted) await stopTcpHttpProxy(id, database.destinationDocker, database.publicPort); + } + await prisma.databaseSettings.deleteMany({ where: { databaseId: id } }); + await prisma.databaseSecret.deleteMany({ where: { databaseId: id } }); + await prisma.database.delete({ where: { id } }); + } + } + return {} + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} export async function getDatabaseStatus(request: FastifyRequest) { try { const { id } = request.params; diff --git a/apps/api/src/routes/api/v1/databases/index.ts b/apps/api/src/routes/api/v1/databases/index.ts index 8f269c8b5..65f0d58f4 100644 --- a/apps/api/src/routes/api/v1/databases/index.ts +++ b/apps/api/src/routes/api/v1/databases/index.ts @@ -1,5 +1,5 @@ import { FastifyPluginAsync } from 'fastify'; -import { deleteDatabase, deleteDatabaseSecret, getDatabase, getDatabaseLogs, getDatabaseSecrets, getDatabaseStatus, getDatabaseTypes, getDatabaseUsage, getVersions, listDatabases, newDatabase, saveDatabase, saveDatabaseDestination, saveDatabaseSecret, saveDatabaseSettings, saveDatabaseType, saveVersion, startDatabase, stopDatabase } from './handlers'; +import { cleanupUnconfiguredDatabases, deleteDatabase, deleteDatabaseSecret, getDatabase, getDatabaseLogs, getDatabaseSecrets, getDatabaseStatus, getDatabaseTypes, getDatabaseUsage, getVersions, listDatabases, newDatabase, saveDatabase, saveDatabaseDestination, saveDatabaseSecret, saveDatabaseSettings, saveDatabaseType, saveVersion, startDatabase, stopDatabase } from './handlers'; import type { OnlyId } from '../../../../types'; @@ -12,6 +12,8 @@ const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get('/', async (request) => await listDatabases(request)); fastify.post('/new', async (request, reply) => await newDatabase(request, reply)); + fastify.post('/cleanup/unconfigured', async (request) => await cleanupUnconfiguredDatabases(request)); + fastify.get('/:id', async (request) => await getDatabase(request)); fastify.post('/:id', async (request, reply) => await saveDatabase(request, reply)); fastify.delete('/:id', async (request) => await deleteDatabase(request)); diff --git a/apps/api/src/routes/api/v1/handlers.ts b/apps/api/src/routes/api/v1/handlers.ts index 815ca3000..c57766ed6 100644 --- a/apps/api/src/routes/api/v1/handlers.ts +++ b/apps/api/src/routes/api/v1/handlers.ts @@ -143,15 +143,29 @@ export async function showDashboard(request: FastifyRequest) { include: { teams: true }, }); const settings = await listSettings(); + let foundUnconfiguredApplication = false; for (const application of applications) { if (!application.buildPack || !application.destinationDockerId || !application.branch || (!application.settings?.isBot && !application?.fqdn)) { foundUnconfiguredApplication = true } } - + let foundUnconfiguredService = false; + for (const service of services) { + if (!service.fqdn) { + foundUnconfiguredService = true + } + } + let foundUnconfiguredDatabase = false; + for (const database of databases) { + if (!database.version) { + foundUnconfiguredDatabase = true + } + } return { foundUnconfiguredApplication, + foundUnconfiguredDatabase, + foundUnconfiguredService, applications, databases, services, diff --git a/apps/api/src/routes/api/v1/services/handlers.ts b/apps/api/src/routes/api/v1/services/handlers.ts index 2207841d2..2dcc434b6 100644 --- a/apps/api/src/routes/api/v1/services/handlers.ts +++ b/apps/api/src/routes/api/v1/services/handlers.ts @@ -36,6 +36,33 @@ export async function newService(request: FastifyRequest, reply: FastifyReply) { return errorHandler({ status, message }) } } +export async function cleanupUnconfiguredServices(request: FastifyRequest) { + try { + const teamId = request.user.teamId; + let services = await prisma.service.findMany({ + where: { teams: { some: { id: teamId === "0" ? undefined : teamId } } }, + include: { destinationDocker: true, teams: true }, + }); + for (const service of services) { + if (!service.fqdn) { + if (service.destinationDockerId) { + await executeDockerCmd({ + dockerId: service.destinationDockerId, + command: `docker ps -a --filter 'label=com.docker.compose.project=${service.id}' --format {{.ID}}|xargs -r -n 1 docker stop -t 0` + }) + await executeDockerCmd({ + dockerId: service.destinationDockerId, + command: `docker ps -a --filter 'label=com.docker.compose.project=${service.id}' --format {{.ID}}|xargs -r -n 1 docker rm --force` + }) + } + await removeService({ id: service.id }); + } + } + return {} + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} export async function getServiceStatus(request: FastifyRequest) { try { const teamId = request.user.teamId; diff --git a/apps/api/src/routes/api/v1/services/index.ts b/apps/api/src/routes/api/v1/services/index.ts index 17ac60fdd..bd0311b4d 100644 --- a/apps/api/src/routes/api/v1/services/index.ts +++ b/apps/api/src/routes/api/v1/services/index.ts @@ -5,6 +5,7 @@ import { checkService, checkServiceDomain, cleanupPlausibleLogs, + cleanupUnconfiguredServices, deleteService, deleteServiceSecret, deleteServiceStorage, @@ -39,6 +40,8 @@ const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get('/', async (request) => await listServices(request)); fastify.post('/new', async (request, reply) => await newService(request, reply)); + fastify.post('/cleanup/unconfigured', async (request) => await cleanupUnconfiguredServices(request)); + fastify.get('/:id', async (request) => await getService(request)); fastify.post('/:id', async (request, reply) => await saveService(request, reply)); fastify.delete('/:id', async (request) => await deleteService(request)); diff --git a/apps/ui/src/routes/databases/[id]/__layout.svelte b/apps/ui/src/routes/databases/[id]/__layout.svelte index 9c8604d25..58daedd82 100644 --- a/apps/ui/src/routes/databases/[id]/__layout.svelte +++ b/apps/ui/src/routes/databases/[id]/__layout.svelte @@ -55,7 +55,6 @@ export let database: any; import { del, get, post } from '$lib/api'; import { t } from '$lib/translations'; - import { goto } from '$app/navigation'; import { page } from '$app/stores'; import { errorNotification, handlerNotFoundLoad } from '$lib/common'; import { appSession, status, isDeploymentEnabled } from '$lib/store'; diff --git a/apps/ui/src/routes/index.svelte b/apps/ui/src/routes/index.svelte index 57cd74baf..23a6559dd 100644 --- a/apps/ui/src/routes/index.svelte +++ b/apps/ui/src/routes/index.svelte @@ -22,6 +22,8 @@