From 7795c524f089cb20e606d85b4d8a0ff3bc4d228c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 20 Jul 2022 13:35:26 +0000 Subject: [PATCH] feat: working on remote docker engine --- apps/api/src/jobs/checkProxies.ts | 48 +- apps/api/src/jobs/deployApplication.ts | 10 +- apps/api/src/lib/common.ts | 596 ++++++++---------- apps/api/src/lib/docker.ts | 41 +- .../routes/api/v1/applications/handlers.ts | 12 +- .../src/routes/api/v1/databases/handlers.ts | 71 ++- apps/api/src/routes/api/v1/databases/index.ts | 3 +- .../routes/api/v1/destinations/handlers.ts | 67 +- .../src/routes/api/v1/destinations/index.ts | 3 +- .../src/routes/api/v1/destinations/types.ts | 4 +- .../src/routes/api/v1/services/handlers.ts | 100 +-- .../src/routes/webhooks/github/handlers.ts | 8 +- .../src/routes/webhooks/gitlab/handlers.ts | 8 +- .../src/routes/databases/[id]/__layout.svelte | 2 +- .../destinations/[id]/_LocalDocker.svelte | 22 +- .../destinations/[id]/_RemoteDocker.svelte | 30 +- .../routes/destinations/[id]/__layout.svelte | 5 +- 17 files changed, 510 insertions(+), 520 deletions(-) diff --git a/apps/api/src/jobs/checkProxies.ts b/apps/api/src/jobs/checkProxies.ts index 6168baf5a..1715d8437 100644 --- a/apps/api/src/jobs/checkProxies.ts +++ b/apps/api/src/jobs/checkProxies.ts @@ -1,24 +1,24 @@ import { parentPort } from 'node:worker_threads'; -import { prisma, startTraefikTCPProxy, generateDatabaseConfiguration, startTraefikProxy, asyncExecShell } from '../lib/common'; +import { prisma, startTraefikTCPProxy, generateDatabaseConfiguration, startTraefikProxy, asyncExecShell, executeDockerCmd } from '../lib/common'; import { checkContainer, getEngine } from '../lib/docker'; (async () => { if (parentPort) { - // Coolify Proxy + // Coolify Proxy local const engine = '/var/run/docker.sock'; const localDocker = await prisma.destinationDocker.findFirst({ where: { engine, network: 'coolify' } }); if (localDocker && localDocker.isCoolifyProxyUsed) { // Remove HAProxy - const found = await checkContainer(engine, 'coolify-haproxy'); - const host = getEngine(engine); + const found = await checkContainer({ dockerId: localDocker.id, container: 'coolify-haproxy' }); if (found) { - await asyncExecShell( - `DOCKER_HOST="${host}" docker stop -t 0 coolify-haproxy && docker rm coolify-haproxy` - ); + await executeDockerCmd({ + dockerId: localDocker.id, + command: `docker stop -t 0 coolify-haproxy && docker rm coolify-haproxy` + }) } - await startTraefikProxy(engine); + await startTraefikProxy(localDocker.id); } @@ -32,12 +32,14 @@ import { checkContainer, getEngine } from '../lib/docker'; if (destinationDockerId && destinationDocker.isCoolifyProxyUsed) { const { privatePort } = generateDatabaseConfiguration(database); // Remove HAProxy - const found = await checkContainer(engine, `haproxy-for-${publicPort}`); - const host = getEngine(engine); + const found = await checkContainer({ + dockerId: localDocker.id, container: `haproxy-for-${publicPort}` + }); if (found) { - await asyncExecShell( - `DOCKER_HOST="${host}" docker stop -t 0 haproxy-for-${publicPort} && docker rm haproxy-for-${publicPort}` - ); + await executeDockerCmd({ + dockerId: localDocker.id, + command: `docker stop -t 0 haproxy-for-${publicPort} && docker rm haproxy-for-${publicPort}` + }) } await startTraefikTCPProxy(destinationDocker, id, publicPort, privatePort); @@ -52,12 +54,12 @@ import { checkContainer, getEngine } from '../lib/docker'; const { destinationDockerId, destinationDocker, id } = service; if (destinationDockerId && destinationDocker.isCoolifyProxyUsed) { // Remove HAProxy - const found = await checkContainer(engine, `haproxy-for-${ftpPublicPort}`); - const host = getEngine(engine); + const found = await checkContainer({ dockerId: localDocker.id, container: `haproxy-for-${ftpPublicPort}` }); if (found) { - await asyncExecShell( - `DOCKER_HOST="${host}" docker stop -t 0 haproxy-for-${ftpPublicPort} && docker rm haproxy-for-${ftpPublicPort} ` - ); + await executeDockerCmd({ + dockerId: localDocker.id, + command: `docker stop -t 0 haproxy -for-${ftpPublicPort} && docker rm haproxy-for-${ftpPublicPort}` + }) } await startTraefikTCPProxy(destinationDocker, id, ftpPublicPort, 22, 'wordpressftp'); } @@ -73,12 +75,12 @@ import { checkContainer, getEngine } from '../lib/docker'; const { destinationDockerId, destinationDocker, id } = service; if (destinationDockerId && destinationDocker.isCoolifyProxyUsed) { // Remove HAProxy - const found = await checkContainer(engine, `${id}-${publicPort}`); - const host = getEngine(engine); + const found = await checkContainer({ dockerId: localDocker.id, container: `${id}-${publicPort}` }); if (found) { - await asyncExecShell( - `DOCKER_HOST="${host}" docker stop -t 0 ${id}-${publicPort} && docker rm ${id}-${publicPort}` - ); + await executeDockerCmd({ + dockerId: localDocker.id, + command: `docker stop -t 0 ${id}-${publicPort} && docker rm ${id}-${publicPort} ` + }) } await startTraefikTCPProxy(destinationDocker, id, publicPort, 9000); } diff --git a/apps/api/src/jobs/deployApplication.ts b/apps/api/src/jobs/deployApplication.ts index b5dbe24d9..8b7cb358e 100644 --- a/apps/api/src/jobs/deployApplication.ts +++ b/apps/api/src/jobs/deployApplication.ts @@ -4,7 +4,7 @@ import fs from 'fs/promises'; import yaml from 'js-yaml'; import { copyBaseConfigurationFiles, makeLabelForStandaloneApplication, saveBuildLog, setDefaultConfiguration } from '../lib/buildPacks/common'; -import { asyncExecShell, createDirectories, decrypt, getDomain, prisma } from '../lib/common'; +import { createDirectories, decrypt, executeDockerCmd, getDomain, prisma } from '../lib/common'; import { dockerInstance, getEngine } from '../lib/docker'; import * as importers from '../lib/importers'; import * as buildpacks from '../lib/buildPacks'; @@ -238,8 +238,8 @@ import * as buildpacks from '../lib/buildPacks'; await saveBuildLog({ line: 'Build image already available - no rebuild required.', buildId, applicationId }); } try { - await asyncExecShell(`DOCKER_HOST=${host} docker stop -t 0 ${imageId}`); - await asyncExecShell(`DOCKER_HOST=${host} docker rm ${imageId}`); + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker stop -t 0 ${imageId}` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker rm ${imageId}` }) } catch (error) { // } @@ -325,9 +325,7 @@ import * as buildpacks from '../lib/buildPacks'; volumes: Object.assign({}, ...composeVolumes) }; await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile)); - await asyncExecShell( - `DOCKER_HOST=${host} docker compose --project-directory ${workdir} up -d` - ); + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` }) await saveBuildLog({ line: 'Deployment successful!', buildId, applicationId }); } catch (error) { await saveBuildLog({ line: error, buildId, applicationId }); diff --git a/apps/api/src/lib/common.ts b/apps/api/src/lib/common.ts index 600f80c55..6bf527d82 100644 --- a/apps/api/src/lib/common.ts +++ b/apps/api/src/lib/common.ts @@ -10,6 +10,8 @@ import crypto from 'crypto'; import { promises as dns } from 'dns'; import { PrismaClient } from '@prisma/client'; import cuid from 'cuid'; +import os from 'os'; +import sshConfig from 'ssh-config' import { checkContainer, getEngine, removeContainer } from './docker'; import { day } from './dayjs'; @@ -113,164 +115,164 @@ export const encrypt = (text: string) => { }; export const supportedServiceTypesAndVersions = [ - { - name: 'plausibleanalytics', - fancyName: 'Plausible Analytics', - baseImage: 'plausible/analytics', - images: ['bitnami/postgresql:13.2.0', 'yandex/clickhouse-server:21.3.2.5'], - versions: ['latest', 'stable'], - recommendedVersion: 'stable', - ports: { - main: 8000 - } - }, - { - name: 'nocodb', - fancyName: 'NocoDB', - baseImage: 'nocodb/nocodb', - versions: ['latest'], - recommendedVersion: 'latest', - ports: { - main: 8080 - } - }, - { - name: 'minio', - fancyName: 'MinIO', - baseImage: 'minio/minio', - versions: ['latest'], - recommendedVersion: 'latest', - ports: { - main: 9001 - } - }, - { - name: 'vscodeserver', - fancyName: 'VSCode Server', - baseImage: 'codercom/code-server', - versions: ['latest'], - recommendedVersion: 'latest', - ports: { - main: 8080 - } - }, - { - name: 'wordpress', - fancyName: 'Wordpress', - baseImage: 'wordpress', - images: ['bitnami/mysql:5.7'], - versions: ['latest', 'php8.1', 'php8.0', 'php7.4', 'php7.3'], - recommendedVersion: 'latest', - ports: { - main: 80 - } - }, - { - name: 'vaultwarden', - fancyName: 'Vaultwarden', - baseImage: 'vaultwarden/server', - versions: ['latest'], - recommendedVersion: 'latest', - ports: { - main: 80 - } - }, - { - name: 'languagetool', - fancyName: 'LanguageTool', - baseImage: 'silviof/docker-languagetool', - versions: ['latest'], - recommendedVersion: 'latest', - ports: { - main: 8010 - } - }, - { - name: 'n8n', - fancyName: 'n8n', - baseImage: 'n8nio/n8n', - versions: ['latest'], - recommendedVersion: 'latest', - ports: { - main: 5678 - } - }, - { - name: 'uptimekuma', - fancyName: 'Uptime Kuma', - baseImage: 'louislam/uptime-kuma', - versions: ['latest'], - recommendedVersion: 'latest', - ports: { - main: 3001 - } - }, - { - name: 'ghost', - fancyName: 'Ghost', - baseImage: 'bitnami/ghost', - images: ['bitnami/mariadb'], - versions: ['latest'], - recommendedVersion: 'latest', - ports: { - main: 2368 - } - }, - { - name: 'meilisearch', - fancyName: 'Meilisearch', - baseImage: 'getmeili/meilisearch', - images: [], - versions: ['latest'], - recommendedVersion: 'latest', - ports: { - main: 7700 - } - }, - { - name: 'umami', - fancyName: 'Umami', - baseImage: 'ghcr.io/mikecao/umami', - images: ['postgres:12-alpine'], - versions: ['postgresql-latest'], - recommendedVersion: 'postgresql-latest', - ports: { - main: 3000 - } - }, - { - name: 'hasura', - fancyName: 'Hasura', - baseImage: 'hasura/graphql-engine', - images: ['postgres:12-alpine'], - versions: ['latest', 'v2.5.1'], - recommendedVersion: 'v2.5.1', - ports: { - main: 8080 - } - }, - { - name: 'fider', - fancyName: 'Fider', - baseImage: 'getfider/fider', - images: ['postgres:12-alpine'], - versions: ['stable'], - recommendedVersion: 'stable', - ports: { - main: 3000 - } - }, - // { - // name: 'moodle', - // fancyName: 'Moodle', - // baseImage: 'bitnami/moodle', - // images: [], - // versions: ['latest', 'v4.0.2'], - // recommendedVersion: 'latest', - // ports: { - // main: 8080 - // } - // } + { + name: 'plausibleanalytics', + fancyName: 'Plausible Analytics', + baseImage: 'plausible/analytics', + images: ['bitnami/postgresql:13.2.0', 'yandex/clickhouse-server:21.3.2.5'], + versions: ['latest', 'stable'], + recommendedVersion: 'stable', + ports: { + main: 8000 + } + }, + { + name: 'nocodb', + fancyName: 'NocoDB', + baseImage: 'nocodb/nocodb', + versions: ['latest'], + recommendedVersion: 'latest', + ports: { + main: 8080 + } + }, + { + name: 'minio', + fancyName: 'MinIO', + baseImage: 'minio/minio', + versions: ['latest'], + recommendedVersion: 'latest', + ports: { + main: 9001 + } + }, + { + name: 'vscodeserver', + fancyName: 'VSCode Server', + baseImage: 'codercom/code-server', + versions: ['latest'], + recommendedVersion: 'latest', + ports: { + main: 8080 + } + }, + { + name: 'wordpress', + fancyName: 'Wordpress', + baseImage: 'wordpress', + images: ['bitnami/mysql:5.7'], + versions: ['latest', 'php8.1', 'php8.0', 'php7.4', 'php7.3'], + recommendedVersion: 'latest', + ports: { + main: 80 + } + }, + { + name: 'vaultwarden', + fancyName: 'Vaultwarden', + baseImage: 'vaultwarden/server', + versions: ['latest'], + recommendedVersion: 'latest', + ports: { + main: 80 + } + }, + { + name: 'languagetool', + fancyName: 'LanguageTool', + baseImage: 'silviof/docker-languagetool', + versions: ['latest'], + recommendedVersion: 'latest', + ports: { + main: 8010 + } + }, + { + name: 'n8n', + fancyName: 'n8n', + baseImage: 'n8nio/n8n', + versions: ['latest'], + recommendedVersion: 'latest', + ports: { + main: 5678 + } + }, + { + name: 'uptimekuma', + fancyName: 'Uptime Kuma', + baseImage: 'louislam/uptime-kuma', + versions: ['latest'], + recommendedVersion: 'latest', + ports: { + main: 3001 + } + }, + { + name: 'ghost', + fancyName: 'Ghost', + baseImage: 'bitnami/ghost', + images: ['bitnami/mariadb'], + versions: ['latest'], + recommendedVersion: 'latest', + ports: { + main: 2368 + } + }, + { + name: 'meilisearch', + fancyName: 'Meilisearch', + baseImage: 'getmeili/meilisearch', + images: [], + versions: ['latest'], + recommendedVersion: 'latest', + ports: { + main: 7700 + } + }, + { + name: 'umami', + fancyName: 'Umami', + baseImage: 'ghcr.io/mikecao/umami', + images: ['postgres:12-alpine'], + versions: ['postgresql-latest'], + recommendedVersion: 'postgresql-latest', + ports: { + main: 3000 + } + }, + { + name: 'hasura', + fancyName: 'Hasura', + baseImage: 'hasura/graphql-engine', + images: ['postgres:12-alpine'], + versions: ['latest', 'v2.5.1'], + recommendedVersion: 'v2.5.1', + ports: { + main: 8080 + } + }, + { + name: 'fider', + fancyName: 'Fider', + baseImage: 'getfider/fider', + images: ['postgres:12-alpine'], + versions: ['stable'], + recommendedVersion: 'stable', + ports: { + main: 3000 + } + }, + // { + // name: 'moodle', + // fancyName: 'Moodle', + // baseImage: 'bitnami/moodle', + // images: [], + // versions: ['latest', 'v4.0.2'], + // recommendedVersion: 'latest', + // ports: { + // main: 8080 + // } + // } ]; export async function checkDoubleBranch(branch: string, projectId: number): Promise { @@ -359,12 +361,9 @@ export async function isDomainConfigured({ return !!(foundApp || foundService || coolifyFqdn); } -export async function getContainerUsage(engine: string, container: string): Promise { - const host = getEngine(engine); +export async function getContainerUsage(dockerId: string, container: string): Promise { try { - const { stdout } = await asyncExecShell( - `DOCKER_HOST="${host}" docker container stats ${container} --no-stream --no-trunc --format "{{json .}}"` - ); + const { stdout } = await executeDockerCmd({ dockerId, command: `docker container stats ${container} --no-stream --no-trunc --format "{{json .}}"` }) return JSON.parse(stdout); } catch (err) { return { @@ -469,20 +468,55 @@ export const supportedDatabaseTypesAndVersions = [ }, { name: 'couchdb', fancyName: 'CouchDB', baseImage: 'bitnami/couchdb', versions: ['3.2.1'] } ]; - -export async function startTraefikProxy(engine: string): Promise { - const host = getEngine(engine); - const found = await checkContainer(engine, 'coolify-proxy', true); - const { proxyPassword, proxyUser, id } = await listSettings(); +export async function createRemoteEngineConfiguration(id: string) { + const homedir = os.homedir(); + const sshKeyFile = `/tmp/id_rsa-${id}` + const { sshKey: { privateKey }, remoteIpAddress, remotePort, remoteUser } = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } }) + await fs.writeFile(sshKeyFile, decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 }) + const config = sshConfig.parse('') + const found = config.find({ Host: remoteIpAddress }) if (!found) { - const { stdout: Config } = await asyncExecShell( - `DOCKER_HOST="${host}" docker network inspect bridge --format '{{json .IPAM.Config }}'` - ); + config.append({ + Host: remoteIpAddress, + Port: remotePort.toString(), + User: remoteUser, + IdentityFile: sshKeyFile, + StrictHostKeyChecking: 'no' + }) + } + try { + await fs.stat(`${homedir}/.ssh/`) + } catch (error) { + await fs.mkdir(`${homedir}/.ssh/`) + } + return await fs.writeFile(`${homedir}/.ssh/config`, sshConfig.stringify(config)) +} +export async function executeDockerCmd({ dockerId, command }: { dockerId: string, command: string }) { + let { remoteEngine, remoteIpAddress, remoteUser, engine } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } }) + if (remoteEngine) engine = `ssh://${remoteUser}@${remoteIpAddress}` + + const host = getEngine(engine) + if (engine.startsWith('ssh://')) { + await createRemoteEngineConfiguration(dockerId) + } + return await asyncExecShell( + `DOCKER_HOST="${host}" ${command}` + ); +} +export async function startTraefikProxy(id: string): Promise { + const { engine, network, remoteEngine } = await prisma.destinationDocker.findUnique({ where: { id } }) + + const found = await checkContainer({ dockerId: id, container: 'coolify-proxy', remove: true }); + const { id: settingsId } = await listSettings(); + + if (!found) { + const { stdout: Config } = await executeDockerCmd({ dockerId: id, command: `docker network inspect ${network} --format '{{json .IPAM.Config }}'` }) const ip = JSON.parse(Config)[0].Gateway; - await asyncExecShell( - `DOCKER_HOST="${host}" docker run --restart always \ + await executeDockerCmd({ + dockerId: id, + command: `docker run --restart always \ --add-host 'host.docker.internal:host-gateway' \ - --add-host 'host.docker.internal:${ip}' \ + ${ip ? `--add-host 'host.docker.internal:${ip}'` : ''} \ -v coolify-traefik-letsencrypt:/etc/traefik/acme \ -v /var/run/docker.sock:/var/run/docker.sock \ --network coolify-infra \ @@ -502,75 +536,56 @@ export async function startTraefikProxy(engine: string): Promise { --certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json \ --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web \ --log.level=error` - ); - await prisma.setting.update({ where: { id }, data: { proxyHash: null } }); - await prisma.destinationDocker.updateMany({ - where: { engine }, + }) + await prisma.setting.update({ where: { id: settingsId }, data: { proxyHash: null } }); + await prisma.destinationDocker.update({ + where: { id }, data: { isCoolifyProxyUsed: true } }); } - await configureNetworkTraefikProxy(engine); + if (!remoteEngine) await configureNetworkTraefikProxy(engine); } export async function configureNetworkTraefikProxy(engine: string): Promise { - const host = getEngine(engine); const destinations = await prisma.destinationDocker.findMany({ where: { engine } }); - const { stdout: networks } = await asyncExecShell( - `DOCKER_HOST="${host}" docker ps -a --filter name=coolify-proxy --format '{{json .Networks}}'` - ); + + const { stdout: networks } = await executeDockerCmd({ + dockerId: '', + command: + `docker ps -a --filter name=coolify-proxy --format '{{json .Networks}}'` + }); const configuredNetworks = networks.replace(/"/g, '').replace('\n', '').split(','); for (const destination of destinations) { if (!configuredNetworks.includes(destination.network)) { - await asyncExecShell( - `DOCKER_HOST="${host}" docker network connect ${destination.network} coolify-proxy` - ); + await executeDockerCmd({ dockerId: destination.id, command: `docker network connect ${destination.network} coolify-proxy` }) } } } export async function stopTraefikProxy( - engine: string + id: string ): Promise<{ stdout: string; stderr: string } | Error> { - const host = getEngine(engine); - const found = await checkContainer(engine, 'coolify-proxy'); - await prisma.destinationDocker.updateMany({ - where: { engine }, + const found = await checkContainer({ dockerId: id, container: 'coolify-proxy' }); + await prisma.destinationDocker.update({ + where: { id }, data: { isCoolifyProxyUsed: false } }); - const { id } = await prisma.setting.findFirst({}); - await prisma.setting.update({ where: { id }, data: { proxyHash: null } }); + const { id: settingsId } = await prisma.setting.findFirst({}); + await prisma.setting.update({ where: { id: settingsId }, data: { proxyHash: null } }); try { if (found) { - await asyncExecShell( - `DOCKER_HOST="${host}" docker stop -t 0 coolify-proxy && docker rm coolify-proxy` - ); + await executeDockerCmd({ + dockerId: id, + command: + `docker stop -t 0 coolify-proxy && docker rm coolify-proxy` + }); + } } catch (error) { return error; } } -export async function startCoolifyProxy(engine: string): Promise { - const host = getEngine(engine); - const found = await checkContainer(engine, 'coolify-haproxy', true); - const { proxyPassword, proxyUser, id } = await listSettings(); - if (!found) { - const { stdout: Config } = await asyncExecShell( - `DOCKER_HOST="${host}" docker network inspect bridge --format '{{json .IPAM.Config }}'` - ); - const ip = JSON.parse(Config)[0].Gateway; - await asyncExecShell( - `DOCKER_HOST="${host}" docker run -e HAPROXY_USERNAME=${proxyUser} -e HAPROXY_PASSWORD=${proxyPassword} --restart always --add-host 'host.docker.internal:host-gateway' --add-host 'host.docker.internal:${ip}' -v coolify-ssl-certs:/usr/local/etc/haproxy/ssl --network coolify-infra -p "80:80" -p "443:443" -p "8404:8404" -p "5555:5555" -p "5000:5000" --name coolify-haproxy -d coollabsio/${defaultProxyImage}` - ); - await prisma.setting.update({ where: { id }, data: { proxyHash: null } }); - await prisma.destinationDocker.updateMany({ - where: { engine }, - data: { isCoolifyProxyUsed: true } - }); - } - await configureNetworkCoolifyProxy(engine); -} - export async function configureNetworkCoolifyProxy(engine: string): Promise { const host = getEngine(engine); const destinations = await prisma.destinationDocker.findMany({ where: { engine } }); @@ -593,29 +608,6 @@ export async function listSettings(): Promise { } - -// export async function stopCoolifyProxy( -// engine: string -// ): Promise<{ stdout: string; stderr: string } | Error> { -// const host = getEngine(engine); -// const found = await checkContainer(engine, 'coolify-haproxy'); -// await prisma.destinationDocker.updateMany({ -// where: { engine }, -// data: { isCoolifyProxyUsed: false } -// }); -// const { id } = await prisma.setting.findFirst({}); -// await prisma.setting.update({ where: { id }, data: { proxyHash: null } }); -// try { -// if (found) { -// await asyncExecShell( -// `DOCKER_HOST="${host}" docker stop -t 0 coolify-haproxy && docker rm coolify-haproxy` -// ); -// } -// } catch (error) { -// return error; -// } -// } - export function generatePassword(length = 24, symbols = false): string { return generator.generate({ length, @@ -900,38 +892,6 @@ export const createDirectories = async ({ }; }; -export async function startTcpProxy( - destinationDocker: any, - id: string, - publicPort: number, - privatePort: number -): Promise<{ stdout: string; stderr: string } | Error> { - const { network, engine } = destinationDocker; - const host = getEngine(engine); - - const containerName = `haproxy-for-${publicPort}`; - const found = await checkContainer(engine, containerName, true); - const foundDependentContainer = await checkContainer(engine, id, true); - try { - if (foundDependentContainer && !found) { - const { stdout: Config } = await asyncExecShell( - `DOCKER_HOST="${host}" docker network inspect bridge --format '{{json .IPAM.Config }}'` - ); - const ip = JSON.parse(Config)[0].Gateway; - return await asyncExecShell( - `DOCKER_HOST=${host} docker run --restart always -e PORT=${publicPort} -e APP=${id} -e PRIVATE_PORT=${privatePort} --add-host 'host.docker.internal:host-gateway' --add-host 'host.docker.internal:${ip}' --network ${network} -p ${publicPort}:${publicPort} --name ${containerName} -d coollabsio/${defaultProxyImageTcp}` - ); - } - if (!foundDependentContainer && found) { - return await asyncExecShell( - `DOCKER_HOST=${host} docker stop -t 0 ${containerName} && docker rm ${containerName}` - ); - } - } catch (error) { - return error; - } -} - export async function stopDatabaseContainer( database: any @@ -940,17 +900,15 @@ export async function stopDatabaseContainer( const { id, destinationDockerId, - destinationDocker: { engine } + destinationDocker: { engine, id: dockerId } } = database; if (destinationDockerId) { try { - const host = getEngine(engine); - const { stdout } = await asyncExecShell( - `DOCKER_HOST=${host} docker inspect --format '{{json .State}}' ${id}` - ); + const { stdout } = await executeDockerCmd({ dockerId, command: `docker inspect --format '{{json .State}}' ${id}` }) + if (stdout) { everStarted = true; - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId }); } } catch (error) { // @@ -966,21 +924,18 @@ export async function stopTcpHttpProxy( publicPort: number, forceName: string = null ): Promise<{ stdout: string; stderr: string } | Error> { - const { engine } = destinationDocker; - const host = getEngine(engine); - const settings = await listSettings(); - let containerName = `${id}-${publicPort}`; - if (!settings.isTraefikUsed) { - containerName = `haproxy-for-${publicPort}`; - } - if (forceName) containerName = forceName; - const found = await checkContainer(engine, containerName); - + const { id: dockerId } = destinationDocker; + let container = `${id}-${publicPort}`; + if (forceName) container = forceName; + const found = await checkContainer({ dockerId, container }); try { if (found) { - return await asyncExecShell( - `DOCKER_HOST=${host} docker stop -t 0 ${containerName} && docker rm ${containerName}` - ); + return await executeDockerCmd({ + dockerId, + command: + `docker stop -t 0 ${container} && docker rm ${container}` + }); + } } catch (error) { return error; @@ -1073,34 +1028,35 @@ export async function startTraefikTCPProxy( privatePort: number, type?: string ): Promise<{ stdout: string; stderr: string } | Error> { - const { network, engine } = destinationDocker; - const host = getEngine(engine); - const containerName = `${id}-${publicPort}`; - const found = await checkContainer(engine, containerName, true); + const { network, id: dockerId } = destinationDocker; + const container = `${id}-${publicPort}`; + const found = await checkContainer({ dockerId, container, remove: true }); let dependentId = id; if (type === 'wordpressftp') dependentId = `${id}-ftp`; - const foundDependentContainer = await checkContainer(engine, dependentId, true); + const foundDependentContainer = await checkContainer({ dockerId, container: dependentId, remove: true }); try { if (foundDependentContainer && !found) { - const { stdout: Config } = await asyncExecShell( - `DOCKER_HOST="${host}" docker network inspect bridge --format '{{json .IPAM.Config }}'` - ); + const { stdout: Config } = await executeDockerCmd({ + dockerId, + command: `docker network inspect ${network} --format '{{json .IPAM.Config }}'` + }) + const ip = JSON.parse(Config)[0].Gateway; const tcpProxy = { version: '3.5', services: { [`${id}-${publicPort}`]: { - container_name: containerName, + container_name: container, image: 'traefik:v2.6', command: [ - `--entrypoints.tcp.address=:${publicPort}`, - `--entryPoints.tcp.forwardedHeaders.insecure=true`, - `--providers.http.endpoint=${otherTraefikEndpoint}?id=${id}&privatePort=${privatePort}&publicPort=${publicPort}&type=tcp&address=${dependentId}`, + `--entrypoints.tcp.address =: ${publicPort}`, + `--entryPoints.tcp.forwardedHeaders.insecure = true`, + `--providers.http.endpoint = ${otherTraefikEndpoint} ? id = ${id} & privatePort=${privatePort} & publicPort=${publicPort} & type=tcp & address=${dependentId}`, '--providers.http.pollTimeout=2s', '--log.level=error' ], - ports: [`${publicPort}:${publicPort}`], - extra_hosts: ['host.docker.internal:host-gateway', `host.docker.internal:${ip}`], + ports: [`${publicPort}: ${publicPort}`], + extra_hosts: ['host.docker.internal:host-gateway', `host.docker.internal: ${ip}`], volumes: ['/var/run/docker.sock:/var/run/docker.sock'], networks: ['coolify-infra', network] } @@ -1117,15 +1073,17 @@ export async function startTraefikTCPProxy( } }; await fs.writeFile(`/tmp/docker-compose-${id}.yaml`, yaml.dump(tcpProxy)); - await asyncExecShell( - `DOCKER_HOST=${host} docker compose -f /tmp/docker-compose-${id}.yaml up -d` - ); + await executeDockerCmd({ + dockerId, + command: `docker compose -f /tmp/docker-compose-${id}.yaml up -d` + }) await fs.rm(`/tmp/docker-compose-${id}.yaml`); } if (!foundDependentContainer && found) { - return await asyncExecShell( - `DOCKER_HOST=${host} docker stop -t 0 ${containerName} && docker rm ${containerName}` - ); + await executeDockerCmd({ + dockerId, + command: `docker stop -t 0 ${container} && docker rm ${container}` + }) } } catch (error) { console.log(error); @@ -1350,7 +1308,7 @@ export async function configureServiceType({ } else if (type === 'moodle') { const defaultUsername = cuid(); const defaultPassword = encrypt(generatePassword()); - const defaultEmail = `${cuid()}@example.com`; + const defaultEmail = `${cuid()} @example.com`; const mariadbUser = cuid(); const mariadbPassword = encrypt(generatePassword()); const mariadbDatabase = 'moodle_db'; @@ -1461,9 +1419,9 @@ export const getServiceMainPort = (service: string) => { export function makeLabelForServices(type) { return [ 'coolify.managed=true', - `coolify.version=${version}`, - `coolify.type=service`, - `coolify.service.type=${type}` + `coolify.version = ${version} `, + `coolify.type = service`, + `coolify.service.type = ${type} ` ]; } export function errorHandler({ status = 500, message = 'Unknown error.' }: { status: number, message: string | any }) { @@ -1489,7 +1447,7 @@ export async function stopBuild(buildId, applicationId) { let count = 0; await new Promise(async (resolve, reject) => { const { destinationDockerId, status } = await prisma.build.findFirst({ where: { id: buildId } }); - const { engine } = await prisma.destinationDocker.findFirst({ where: { id: destinationDockerId } }); + const { engine, id: dockerId } = await prisma.destinationDocker.findFirst({ where: { id: destinationDockerId } }); const host = getEngine(engine); let interval = setInterval(async () => { try { @@ -1503,15 +1461,15 @@ export async function stopBuild(buildId, applicationId) { } const { stdout: buildContainers } = await asyncExecShell( - `DOCKER_HOST=${host} docker container ls --filter "label=coolify.buildId=${buildId}" --format '{{json .}}'` + `DOCKER_HOST = ${host} docker container ls--filter "label=coolify.buildId=${buildId}" --format '{{json .}}'` ); if (buildContainers) { const containersArray = buildContainers.trim().split('\n'); for (const container of containersArray) { const containerObj = JSON.parse(container); const id = containerObj.ID; - if (!containerObj.Names.startsWith(`${applicationId}`)) { - await removeContainer({ id, engine }); + if (!containerObj.Names.startsWith(`${applicationId} `)) { + await removeContainer({ id, dockerId }); await cleanupDB(buildId); clearInterval(interval); return resolve(); diff --git a/apps/api/src/lib/docker.ts b/apps/api/src/lib/docker.ts index 730666590..cded70acf 100644 --- a/apps/api/src/lib/docker.ts +++ b/apps/api/src/lib/docker.ts @@ -1,4 +1,4 @@ -import { asyncExecShell } from './common'; +import { asyncExecShell, executeDockerCmd } from './common'; import Dockerode from 'dockerode'; export function getEngine(engine: string): string { return engine === '/var/run/docker.sock' ? 'unix:///var/run/docker.sock' : engine; @@ -12,22 +12,31 @@ export function dockerInstance({ destinationDocker }): { engine: Dockerode; netw }; } -export async function checkContainer(engine: string, container: string, remove = false): Promise { - const host = getEngine(engine); +export async function checkContainer({ dockerId, container, remove = false }: { dockerId: string, container: string, remove?: boolean }): Promise { let containerFound = false; - try { - const { stdout } = await asyncExecShell( - `DOCKER_HOST="${host}" docker inspect --format '{{json .State}}' ${container}` - ); + const { stdout } = await executeDockerCmd({ + dockerId, + command: + `docker inspect --format '{{json .State}}' ${container}` + }); + const parsedStdout = JSON.parse(stdout); const status = parsedStdout.Status; const isRunning = status === 'running'; if (status === 'created') { - await asyncExecShell(`DOCKER_HOST="${host}" docker rm ${container}`); + await executeDockerCmd({ + dockerId, + command: + `docker rm ${container}` + }); } if (remove && status === 'exited') { - await asyncExecShell(`DOCKER_HOST="${host}" docker rm ${container}`); + await executeDockerCmd({ + dockerId, + command: + `docker rm ${container}` + }); } if (isRunning) { containerFound = true; @@ -57,19 +66,17 @@ export async function isContainerExited(engine: string, containerName: string): export async function removeContainer({ id, - engine + dockerId }: { id: string; - engine: string; + dockerId: string; }): Promise { - const host = getEngine(engine); try { - const { stdout } = await asyncExecShell( - `DOCKER_HOST=${host} docker inspect --format '{{json .State}}' ${id}` - ); + const { stdout } =await executeDockerCmd({ dockerId, command: `docker inspect --format '{{json .State}}' ${id}`}) + if (JSON.parse(stdout).Running) { - await asyncExecShell(`DOCKER_HOST=${host} docker stop -t 0 ${id}`); - await asyncExecShell(`DOCKER_HOST=${host} docker rm ${id}`); + await executeDockerCmd({ dockerId, command: `docker stop -t 0 ${id}`}) + await executeDockerCmd({ dockerId, command: `docker rm ${id}`}) } } catch (error) { console.log(error); diff --git a/apps/api/src/routes/api/v1/applications/handlers.ts b/apps/api/src/routes/api/v1/applications/handlers.ts index 5cb32db22..6c73361d7 100644 --- a/apps/api/src/routes/api/v1/applications/handlers.ts +++ b/apps/api/src/routes/api/v1/applications/handlers.ts @@ -72,7 +72,7 @@ export async function getApplication(request: FastifyRequest) { let isExited = false; const application: any = await getApplicationFromDB(id, teamId); if (application?.destinationDockerId && application.destinationDocker?.engine) { - isRunning = await checkContainer(application.destinationDocker.engine, id); + isRunning = await checkContainer({ dockerId: application.destinationDocker.id, container: id }); isExited = await isContainerExited(application.destinationDocker.engine, id); } return { @@ -285,10 +285,10 @@ export async function stopApplication(request: FastifyRequest, reply: Fa const { teamId } = request.user const application: any = await getApplicationFromDB(id, teamId); if (application?.destinationDockerId && application.destinationDocker?.engine) { - const { engine } = application.destinationDocker; - const found = await checkContainer(engine, id); + const { engine, id: dockerId } = application.destinationDocker; + const found = await checkContainer({ dockerId, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: application.destinationDocker.id }); } } return reply.code(201).send(); @@ -314,7 +314,7 @@ export async function deleteApplication(request: FastifyRequest) { + try { + const { id } = request.params; + const teamId = request.user.teamId; + let isRunning = false; + + const database = await prisma.database.findFirst({ + where: { id, teams: { some: { id: teamId === '0' ? undefined : teamId } } }, + include: { destinationDocker: true, settings: true } + }); + const { destinationDockerId, destinationDocker } = database; + if (destinationDockerId) { + try { + const { stdout } = await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker inspect --format '{{json .State}}' ${id}` }) + + if (JSON.parse(stdout).Running) { + isRunning = true; + } + } catch (error) { + // + } + } + return { + isRunning + } + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} + export async function getDatabase(request: FastifyRequest) { try { const { id } = request.params; @@ -68,30 +98,12 @@ export async function getDatabase(request: FastifyRequest) { throw { status: 404, message: 'Database not found.' } } if (database.dbUserPassword) database.dbUserPassword = decrypt(database.dbUserPassword); - if (database.rootUserPassword) database.rootUserPassword = decrypt(database.rootUserPassword); - const { destinationDockerId, destinationDocker } = database; - let isRunning = false; - if (destinationDockerId) { - const host = getEngine(destinationDocker.engine); - - try { - const { stdout } = await asyncExecShell( - `DOCKER_HOST=${host} docker inspect --format '{{json .State}}' ${id}` - ); - - if (JSON.parse(stdout).Running) { - isRunning = true; - } - } catch (error) { - // - } - } + if (database.rootUserPassword) database.rootUserPassword = decrypt(database.rootUserPassword); const configuration = generateDatabaseConfiguration(database); const settings = await listSettings(); return { privatePort: configuration?.privatePort, database, - isRunning, versions: await getDatabaseVersions(database.type), settings }; @@ -164,16 +176,15 @@ export async function saveDatabaseDestination(request: FastifyRequest) { if (database.dbUserPassword) database.dbUserPassword = decrypt(database.dbUserPassword); if (database.rootUserPassword) database.rootUserPassword = decrypt(database.rootUserPassword); if (database.destinationDockerId) { - [usage] = await Promise.all([getContainerUsage(database.destinationDocker.engine, id)]); + [usage] = await Promise.all([getContainerUsage(database.destinationDocker.id, id)]); } return { usage @@ -267,13 +278,13 @@ export async function startDatabase(request: FastifyRequest) { const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); try { - await asyncExecShell(`DOCKER_HOST=${host} docker volume create ${volumeName}`); + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker volume create ${volumeName}` }) } catch (error) { console.log(error); } try { - await asyncExecShell(`DOCKER_HOST=${host} docker compose -f ${composeFileDestination} up -d`); - if (isPublic) await startTcpProxy(destinationDocker, id, publicPort, privatePort); + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up -d` }) + if (isPublic) await startTraefikTCPProxy(destinationDocker, id, publicPort, privatePort); return {}; } catch (error) { throw { @@ -453,11 +464,7 @@ export async function saveDatabaseSettings(request: FastifyRequest => { fastify.post('/new', async (request, reply) => await newDatabase(request, reply)); fastify.get('/:id', async (request) => await getDatabase(request)); + fastify.get('/:id/status', async (request) => await getDatabaseStatus(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/destinations/handlers.ts b/apps/api/src/routes/api/v1/destinations/handlers.ts index ff3596f4d..c8f1be658 100644 --- a/apps/api/src/routes/api/v1/destinations/handlers.ts +++ b/apps/api/src/routes/api/v1/destinations/handlers.ts @@ -2,7 +2,7 @@ import type { FastifyRequest } from 'fastify'; import { FastifyReply } from 'fastify'; import sshConfig from 'ssh-config' import fs from 'fs/promises' -import { asyncExecShell, decrypt, errorHandler, listSettings, prisma, startCoolifyProxy, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common'; +import { asyncExecShell, decrypt, errorHandler, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common'; import { checkContainer, dockerInstance, getEngine } from '../../../../lib/docker'; import type { OnlyId } from '../../../../types'; @@ -55,23 +55,8 @@ export async function getDestination(request: FastifyRequest) { const settings = await listSettings(); let payload = { destination, - settings, - state: false + settings }; - - if (destination?.remoteEngine) { - // const { stdout } = await asyncExecShell( - // `ssh -p ${destination.port} ${destination.user}@${destination.ipAddress} "docker ps -a"` - // ); - // console.log(stdout) - // const engine = await generateRemoteEngine(destination); - // // await saveSshKey(destination); - // payload.state = await checkContainer(engine, 'coolify-haproxy'); - } else { - const containerName = 'coolify-proxy'; - payload.state = - destination?.engine && (await checkContainer(destination.engine, containerName)); - } return { ...payload }; @@ -83,7 +68,7 @@ export async function getDestination(request: FastifyRequest) { export async function newDestination(request: FastifyRequest, reply: FastifyReply) { try { const { id } = request.params - let { name, network, engine, isCoolifyProxyUsed, ipAddress, user, port, sshPrivateKey } = request.body + let { name, network, engine, isCoolifyProxyUsed, remoteIpAddress, remoteUser, remotePort } = request.body const teamId = request.user.teamId; if (id === 'new') { if (engine) { @@ -111,16 +96,14 @@ export async function newDestination(request: FastifyRequest, re if (isCoolifyProxyUsed) { const settings = await prisma.setting.findFirst(); if (settings?.isTraefikUsed) { - await startTraefikProxy(engine); - } else { - await startCoolifyProxy(engine); + await startTraefikProxy(id); } } return reply.code(201).send({ id: destination.id }); } - if (ipAddress) { + if (remoteIpAddress) { await prisma.destinationDocker.create({ - data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed, remoteEngine: true, remoteIpAddress: ipAddress, remoteUser: user, remotePort: port } + data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed, remoteEngine: true, remoteIpAddress, remoteUser, remotePort } }); return reply.code(201).send() @@ -180,35 +163,39 @@ export async function saveDestinationSettings(request: FastifyRequest) { - const { engine } = request.body; + const { id } = request.params try { - await startTraefikProxy(engine); + await startTraefikProxy(id); return {} } catch ({ status, message }) { - await stopTraefikProxy(engine); + await stopTraefikProxy(id); return errorHandler({ status, message }) } } export async function stopProxy(request: FastifyRequest) { - const { engine } = request.body; + const { id } = request.params try { - await stopTraefikProxy(engine); + await stopTraefikProxy(id); return {} } catch ({ status, message }) { return errorHandler({ status, message }) } } export async function restartProxy(request: FastifyRequest) { - const { engine } = request.body; + const { id } = request.params try { - await stopTraefikProxy(engine); - await startTraefikProxy(engine); - await prisma.destinationDocker.updateMany({ - where: { engine }, + await stopTraefikProxy(id); + await startTraefikProxy(id); + await prisma.destinationDocker.update({ + where: { id }, data: { isCoolifyProxyUsed: true } }); return {} } catch ({ status, message }) { + await prisma.destinationDocker.update({ + where: { id }, + data: { isCoolifyProxyUsed: false } + }); return errorHandler({ status, message }) } } @@ -217,7 +204,6 @@ export async function assignSSHKey(request: FastifyRequest) { try { const { id: sshKeyId } = request.body; const { id } = request.params; - console.log({ id, sshKeyId }) await prisma.destinationDocker.update({ where: { id }, data: { sshKey: { connect: { id: sshKeyId } } } }) return {} } catch ({ status, message }) { @@ -254,3 +240,16 @@ export async function verifyRemoteDockerEngine(request: FastifyRequest, reply: F return errorHandler({ status, message }) } } + +export async function getDestinationStatus(request: FastifyRequest) { + try { + const { id } = request.params + const destination = await prisma.destinationDocker.findUnique({ where: { id } }) + const containerName = 'coolify-proxy'; + return { + isRunning: await checkContainer({ dockerId: destination.id, container: containerName }) + } + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} diff --git a/apps/api/src/routes/api/v1/destinations/index.ts b/apps/api/src/routes/api/v1/destinations/index.ts index 46897817b..3be168f29 100644 --- a/apps/api/src/routes/api/v1/destinations/index.ts +++ b/apps/api/src/routes/api/v1/destinations/index.ts @@ -1,5 +1,5 @@ import { FastifyPluginAsync } from 'fastify'; -import { assignSSHKey, checkDestination, deleteDestination, getDestination, listDestinations, newDestination, restartProxy, saveDestinationSettings, startProxy, stopProxy, verifyRemoteDockerEngine } from './handlers'; +import { assignSSHKey, checkDestination, deleteDestination, getDestination, getDestinationStatus, listDestinations, newDestination, restartProxy, saveDestinationSettings, startProxy, stopProxy, verifyRemoteDockerEngine } from './handlers'; import type { OnlyId } from '../../../../types'; import type { CheckDestination, NewDestination, Proxy, SaveDestinationSettings } from './types'; @@ -14,6 +14,7 @@ const root: FastifyPluginAsync = async (fastify): Promise => { fastify.get('/:id', async (request) => await getDestination(request)); fastify.post('/:id', async (request, reply) => await newDestination(request, reply)); fastify.delete('/:id', async (request) => await deleteDestination(request)); + fastify.get('/:id/status', async (request) => await getDestinationStatus(request)); fastify.post('/:id/settings', async (request) => await saveDestinationSettings(request)); fastify.post('/:id/start', async (request,) => await startProxy(request)); diff --git a/apps/api/src/routes/api/v1/destinations/types.ts b/apps/api/src/routes/api/v1/destinations/types.ts index 25691b9d8..d95c215b5 100644 --- a/apps/api/src/routes/api/v1/destinations/types.ts +++ b/apps/api/src/routes/api/v1/destinations/types.ts @@ -20,7 +20,5 @@ export interface SaveDestinationSettings extends OnlyId { } } export interface Proxy extends OnlyId { - Body: { - engine: string - } + } \ No newline at end of file diff --git a/apps/api/src/routes/api/v1/services/handlers.ts b/apps/api/src/routes/api/v1/services/handlers.ts index 74658fc47..d04f4554d 100644 --- a/apps/api/src/routes/api/v1/services/handlers.ts +++ b/apps/api/src/routes/api/v1/services/handlers.ts @@ -282,7 +282,7 @@ export async function getServiceUsage(request: FastifyRequest) { const service = await getServiceFromDB({ id, teamId }); if (service.destinationDockerId) { - [usage] = await Promise.all([getContainerUsage(service.destinationDocker.engine, id)]); + [usage] = await Promise.all([getContainerUsage(service.destinationDocker.id, id)]); } return { usage @@ -877,17 +877,17 @@ async function stopPlausibleAnalyticsService(request: FastifyRequest) { const { destinationDockerId, destinationDocker, fqdn } = service; if (destinationDockerId) { const engine = destinationDocker.engine; - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } return {} @@ -1075,9 +1075,9 @@ async function stopMinioService(request: FastifyRequest) { await prisma.minio.update({ where: { serviceId: id }, data: { publicPort: null } }) if (destinationDockerId) { const engine = destinationDocker.engine; - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } return {} @@ -1199,9 +1199,9 @@ async function stopVscodeService(request: FastifyRequest) { const { destinationDockerId, destinationDocker, fqdn } = service; if (destinationDockerId) { const engine = destinationDocker.engine; - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } return {} @@ -1348,26 +1348,26 @@ async function stopWordpressService(request: FastifyRequest) { if (destinationDockerId) { const engine = destinationDocker.engine; try { - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); } try { - const found = await checkContainer(engine, `${id}-mysql`); + const found = await checkContainer({ dockerId: destinationDocker.id, container: `${id}-mysql` }); if (found) { - await removeContainer({ id: `${id}-mysql`, engine }); + await removeContainer({ id: `${id}-mysql`, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); } try { if (ftpEnabled) { - const found = await checkContainer(engine, `${id}-ftp`); + const found = await checkContainer({ dockerId: destinationDocker.id, container: `${id}-ftp` }); if (found) { - await removeContainer({ id: `${id}-ftp`, engine }); + await removeContainer({ id: `${id}-ftp`, dockerId: destinationDocker.id }); } await prisma.wordpress.update({ where: { serviceId: id }, @@ -1461,9 +1461,9 @@ async function stopVaultwardenService(request: FastifyRequest) const engine = destinationDocker.engine; try { - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); @@ -1553,9 +1553,9 @@ async function stopLanguageToolService(request: FastifyRequest const engine = destinationDocker.engine; try { - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); @@ -1645,9 +1645,9 @@ async function stopN8nService(request: FastifyRequest) { const engine = destinationDocker.engine; try { - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); @@ -1736,9 +1736,9 @@ async function stopUptimekumaService(request: FastifyRequest) const engine = destinationDocker.engine; try { - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); @@ -1888,13 +1888,13 @@ async function stopGhostService(request: FastifyRequest) { const engine = destinationDocker.engine; try { - let found = await checkContainer(engine, id); + let found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } - found = await checkContainer(engine, `${id}-mariadb`); + found = await checkContainer({ dockerId: destinationDocker.id, container: `${id}-mariadb` }); if (found) { - await removeContainer({ id: `${id}-mariadb`, engine }); + await removeContainer({ id: `${id}-mariadb`, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); @@ -1989,9 +1989,9 @@ async function stopMeilisearchService(request: FastifyRequest) const engine = destinationDocker.engine; try { - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); @@ -2208,17 +2208,17 @@ async function stopUmamiService(request: FastifyRequest) { const engine = destinationDocker.engine; try { - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); } try { - const found = await checkContainer(engine, `${id}-postgresql`); + const found = await checkContainer({ dockerId: destinationDocker.id, container: `${id}-postgresql` }); if (found) { - await removeContainer({ id: `${id}-postgresql`, engine }); + await removeContainer({ id: `${id}-postgresql`, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); @@ -2344,17 +2344,17 @@ async function stopHasuraService(request: FastifyRequest) { const engine = destinationDocker.engine; try { - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); } try { - const found = await checkContainer(engine, `${id}-postgresql`); + const found = await checkContainer({ dockerId: destinationDocker.id, container: `${id}-postgresql` }); if (found) { - await removeContainer({ id: `${id}-postgresql`, engine }); + await removeContainer({ id: `${id}-postgresql`, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); @@ -2507,17 +2507,17 @@ async function stopFiderService(request: FastifyRequest) { const engine = destinationDocker.engine; try { - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); } try { - const found = await checkContainer(engine, `${id}-postgresql`); + const found = await checkContainer({ dockerId: destinationDocker.id, container: `${id}-postgresql` }); if (found) { - await removeContainer({ id: `${id}-postgresql`, engine }); + await removeContainer({ id: `${id}-postgresql`, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); @@ -2670,17 +2670,17 @@ async function stopMoodleService(request: FastifyRequest) { const engine = destinationDocker.engine; try { - const found = await checkContainer(engine, id); + const found = await checkContainer({ dockerId: destinationDocker.id, container: id }); if (found) { - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); } try { - const found = await checkContainer(engine, `${id}-mariadb`); + const found = await checkContainer({ dockerId: destinationDocker.id, container: `${id}-mariadb` }); if (found) { - await removeContainer({ id: `${id}-mariadb`, engine }); + await removeContainer({ id: `${id}-mariadb`, dockerId: destinationDocker.id }); } } catch (error) { console.error(error); @@ -2789,7 +2789,7 @@ export async function activateWordpressFtp(request: FastifyRequest): Promi if (applicationFound.settings.previews) { if (applicationFound.destinationDockerId) { const isRunning = await checkContainer( - applicationFound.destinationDocker.engine, - applicationFound.id + { + dockerId: applicationFound.destinationDocker.engine, + container: applicationFound.id + } ); if (!isRunning) { throw { status: 500, message: 'Application not running.' } @@ -205,7 +207,7 @@ export async function gitHubEvents(request: FastifyRequest): Promi if (applicationFound.destinationDockerId) { const id = `${applicationFound.id}-${pullmergeRequestId}`; const engine = applicationFound.destinationDocker.engine; - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: applicationFound.destinationDocker.id }); } return { message: 'Removed preview. Thank you!' diff --git a/apps/api/src/routes/webhooks/gitlab/handlers.ts b/apps/api/src/routes/webhooks/gitlab/handlers.ts index dfe310ed7..d6d1a43cd 100644 --- a/apps/api/src/routes/webhooks/gitlab/handlers.ts +++ b/apps/api/src/routes/webhooks/gitlab/handlers.ts @@ -117,8 +117,10 @@ export async function gitLabEvents(request: FastifyRequest) { if (applicationFound.settings.previews) { if (applicationFound.destinationDockerId) { const isRunning = await checkContainer( - applicationFound.destinationDocker.engine, - applicationFound.id + { + dockerId: applicationFound.destinationDocker.engine, + container: applicationFound.id + } ); if (!isRunning) { throw { status: 500, message: 'Application not running.' } @@ -164,7 +166,7 @@ export async function gitLabEvents(request: FastifyRequest) { if (applicationFound.destinationDockerId) { const id = `${applicationFound.id}-${pullmergeRequestId}`; const engine = applicationFound.destinationDocker.engine; - await removeContainer({ id, engine }); + await removeContainer({ id, dockerId: applicationFound.destinationDocker.id }); } return { message: 'Removed preview. Thank you!' diff --git a/apps/ui/src/routes/databases/[id]/__layout.svelte b/apps/ui/src/routes/databases/[id]/__layout.svelte index cfd575583..c17dae679 100644 --- a/apps/ui/src/routes/databases/[id]/__layout.svelte +++ b/apps/ui/src/routes/databases/[id]/__layout.svelte @@ -104,7 +104,7 @@ async function getStatus() { if ($status.database.loading) return; $status.database.loading = true; - const data = await get(`/databases/${id}`); + const data = await get(`/databases/${id}/status`); $status.database.isRunning = data.isRunning; $status.database.initialLoading = false; $status.database.loading = false; diff --git a/apps/ui/src/routes/destinations/[id]/_LocalDocker.svelte b/apps/ui/src/routes/destinations/[id]/_LocalDocker.svelte index cad681963..210809e84 100644 --- a/apps/ui/src/routes/destinations/[id]/_LocalDocker.svelte +++ b/apps/ui/src/routes/destinations/[id]/_LocalDocker.svelte @@ -1,22 +1,24 @@