diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 0d5cfe9e0..366ed5e1c 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -9,7 +9,7 @@ import autoLoad from '@fastify/autoload'; import socketIO from 'fastify-socket.io' import socketIOServer from './realtime' -import { cleanupDockerStorage, createRemoteEngineConfiguration, decrypt, executeCommand, executeSSHCmd, generateDatabaseConfiguration, isDev, listSettings, prisma, sentryDSN, startTraefikProxy, startTraefikTCPProxy, version } from './lib/common'; +import { cleanupDockerStorage, createRemoteEngineConfiguration, decrypt, executeCommand, generateDatabaseConfiguration, isDev, listSettings, prisma, sentryDSN, startTraefikProxy, startTraefikTCPProxy, version } from './lib/common'; import { scheduler } from './lib/scheduler'; import { compareVersions } from 'compare-versions'; import Graceful from '@ladjs/graceful' @@ -465,9 +465,9 @@ async function copySSLCertificates() { async function copyRemoteCertificates(id: string, dockerId: string, remoteIpAddress: string) { try { await executeCommand({ command: `scp /tmp/${id}-cert.pem /tmp/${id}-key.pem ${remoteIpAddress}:/tmp/` }) - await executeSSHCmd({ dockerId, command: `docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'` }) - await executeSSHCmd({ dockerId, command: `docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/` }) - await executeSSHCmd({ dockerId, command: `docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/` }) + await executeCommand({ sshCommand: true, shell: true, dockerId, command: `docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'` }) + await executeCommand({ sshCommand: true, dockerId, command: `docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/` }) + await executeCommand({ sshCommand: true, dockerId, command: `docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/` }) } catch (error) { console.log({ error }) } diff --git a/apps/api/src/jobs/deployApplication.ts b/apps/api/src/jobs/deployApplication.ts index f6843281f..90afea210 100644 --- a/apps/api/src/jobs/deployApplication.ts +++ b/apps/api/src/jobs/deployApplication.ts @@ -159,8 +159,8 @@ import * as buildpacks from '../lib/buildPacks'; volumes: Object.assign({}, ...composeVolumes) }; await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile)); - await executeCommand({ dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` }) - await saveBuildLog({ line: 'Deployed successfully', buildId, applicationId }); + await executeCommand({ debug: true, dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` }) + await saveBuildLog({ line: 'Deployed 🎉', buildId, applicationId }); } catch (error) { await saveBuildLog({ line: error, buildId, applicationId }); const foundBuild = await prisma.build.findUnique({ where: { id: buildId } }) @@ -502,15 +502,13 @@ import * as buildpacks from '../lib/buildPacks'; throw new Error(`Build pack ${buildPack} not found.`); } } else { - if (imageFoundRemotely) { + if (imageFoundRemotely || deployNeeded) { await saveBuildLog({ line: `Container image ${imageFound} found in Docker Registry - reuising it`, buildId, applicationId }); } else { - if (imageFoundLocally) { + if (imageFoundLocally || deployNeeded) { await saveBuildLog({ line: `Container image ${imageFound} found locally - reuising it`, buildId, applicationId }); } } - - } if (buildPack === 'compose') { @@ -532,8 +530,9 @@ import * as buildpacks from '../lib/buildPacks'; // } try { + console.log({ debug }) await executeCommand({ debug, buildId, applicationId, dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` }) - await saveBuildLog({ line: 'Deployed successfully', buildId, applicationId }); + await saveBuildLog({ line: 'Deployed 🎉', buildId, applicationId }); await prisma.build.update({ where: { id: buildId }, data: { status: 'success' } }); await prisma.application.update({ where: { id: applicationId }, @@ -633,8 +632,8 @@ import * as buildpacks from '../lib/buildPacks'; volumes: Object.assign({}, ...composeVolumes) }; await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile)); - await executeCommand({ dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` }) - await saveBuildLog({ line: 'Deployed successfully', buildId, applicationId }); + await executeCommand({ debug, dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` }) + await saveBuildLog({ line: 'Deployed 🎉', buildId, applicationId }); } catch (error) { await saveBuildLog({ line: error, buildId, applicationId }); const foundBuild = await prisma.build.findUnique({ where: { id: buildId } }) diff --git a/apps/api/src/lib/buildPacks/common.ts b/apps/api/src/lib/buildPacks/common.ts index 9800ccc70..45ede04a1 100644 --- a/apps/api/src/lib/buildPacks/common.ts +++ b/apps/api/src/lib/buildPacks/common.ts @@ -1,4 +1,4 @@ -import { base64Encode, decrypt, encrypt, executeCommand, generateTimestamp, getDomain, isARM, isDev, prisma, version } from "../common"; +import { base64Encode, decrypt, encrypt, executeCommand, generateTimestamp, getDomain, isARM, isDev, prisma, version } from "../common"; import { promises as fs } from 'fs'; import { day } from "../dayjs"; @@ -489,6 +489,8 @@ export const saveBuildLog = async ({ buildId: string; applicationId: string; }): Promise => { + if (buildId === 'undefined' || buildId === 'null' || !buildId) return; + if (applicationId === 'undefined' || applicationId === 'null' || !applicationId) return; const { default: got } = await import('got') if (typeof line === 'object' && line) { if (line.shortMessage) { @@ -656,17 +658,12 @@ export async function buildImage({ location = await saveDockerRegistryCredentials({ url, username, password, workdir }) } - await executeCommand({ debug, buildId, applicationId, dockerId, command: `docker ${location ? `--config ${location}` : ''} build --progress plain -f ${workdir}/${dockerFile} -t ${cache} --build-arg SOURCE_COMMIT=${commit} ${workdir}` }) + await executeCommand({ stream: true, debug, buildId, applicationId, dockerId, command: `docker ${location ? `--config ${location}` : ''} build --progress plain -f ${workdir}/${dockerFile} -t ${cache} --build-arg SOURCE_COMMIT=${commit} ${workdir}` }) const { status } = await prisma.build.findUnique({ where: { id: buildId } }) if (status === 'canceled') { throw new Error('Canceled.') } - if (isCache) { - await saveBuildLog({ line: `Built successfully`, buildId, applicationId }); - } else { - await saveBuildLog({ line: `Built successfully`, buildId, applicationId }); - } } export function makeLabelForSimpleDockerfile({ applicationId, port, type }) { return [ diff --git a/apps/api/src/lib/buildPacks/compose.ts b/apps/api/src/lib/buildPacks/compose.ts index d7e00a8d9..c73ddb9bd 100644 --- a/apps/api/src/lib/buildPacks/compose.ts +++ b/apps/api/src/lib/buildPacks/compose.ts @@ -109,7 +109,7 @@ export default async function (data) { dockerComposeYaml['networks'] = Object.assign({ ...networks }, { [network]: { external: true } }) await fs.writeFile(fileYaml, yaml.dump(dockerComposeYaml)); await executeCommand({ debug, buildId, applicationId, dockerId, command: `docker compose --project-directory ${workdir} pull` }) - await saveBuildLog({ line: 'Pulling images from Compose file', buildId, applicationId }); + await saveBuildLog({ line: 'Pulling images from Compose file...', buildId, applicationId }); await executeCommand({ debug, buildId, applicationId, dockerId, command: `docker compose --project-directory ${workdir} build --progress plain` }) - await saveBuildLog({ line: 'Building images from Compose file', buildId, applicationId }); + await saveBuildLog({ line: 'Building images from Compose file...', buildId, applicationId }); } diff --git a/apps/api/src/lib/buildPacks/heroku.ts b/apps/api/src/lib/buildPacks/heroku.ts index bb26d79c0..7ba131082 100644 --- a/apps/api/src/lib/buildPacks/heroku.ts +++ b/apps/api/src/lib/buildPacks/heroku.ts @@ -4,14 +4,13 @@ import { saveBuildLog } from "./common"; export default async function (data: any): Promise { const { buildId, applicationId, tag, dockerId, debug, workdir, baseDirectory, baseImage } = data try { - await saveBuildLog({ line: `Building image started.`, buildId, applicationId }); + await saveBuildLog({ line: `Building production image...`, buildId, applicationId }); await executeCommand({ buildId, debug, dockerId, command: `pack build -p ${workdir}${baseDirectory} ${applicationId}:${tag} --builder ${baseImage}` }) - await saveBuildLog({ line: `Building image successful.`, buildId, applicationId }); } catch (error) { throw error; } diff --git a/apps/api/src/lib/common.ts b/apps/api/src/lib/common.ts index 7dcd58e73..5e280e9ea 100644 --- a/apps/api/src/lib/common.ts +++ b/apps/api/src/lib/common.ts @@ -543,7 +543,7 @@ export async function createRemoteEngineConfiguration(id: string) { } return await fs.writeFile(`${homedir}/.ssh/config`, sshConfig.stringify(config)); } -export async function executeCommand({ command, dockerId = null, sshCommand = false, shell = false, buildId, applicationId, debug }: { command: string, sshCommand?: boolean, shell?: boolean, dockerId?: string, buildId?: string, applicationId?: string, debug?: boolean }): Promise> { +export async function executeCommand({ command, dockerId = null, sshCommand = false, shell = false, stream = false, buildId, applicationId, debug }: { command: string, sshCommand?: boolean, shell?: boolean, stream?: boolean, dockerId?: string, buildId?: string, applicationId?: string, debug?: boolean }): Promise> { const { execa, execaCommand } = await import('execa') const { parse } = await import('shell-quote') const parsedCommand = parse(command); @@ -569,66 +569,78 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa } return await execa('ssh', [`${remoteIpAddress}-remote`, ...dockerArgs]); } - return await new Promise(async (resolve, reject) => { - let subprocess = null; + if (stream) { + return await new Promise(async (resolve, reject) => { + let subprocess = null; + if (shell) { + subprocess = execaCommand(command, { + env: { DOCKER_BUILDKIT: '1', DOCKER_HOST: engine } + }); + } else { + subprocess = execa(dockerCommand, dockerArgs, { + env: { DOCKER_BUILDKIT: '1', DOCKER_HOST: engine } + }); + } + const logs = []; + subprocess.stdout.on('data', async (data) => { + const stdout = data.toString(); + const array = stdout.split('\n'); + for (const line of array) { + if (line !== '\n' && line !== '') { + const log = { + line: `${line.replace('\n', '')}`, + buildId, + applicationId + } + logs.push(log); + if (debug) { + await saveBuildLog(log); + } + } + } + }); + subprocess.stderr.on('data', async (data) => { + const stderr = data.toString(); + const array = stderr.split('\n'); + for (const line of array) { + if (line !== '\n' && line !== '') { + const log = { + line: `${line.replace('\n', '')}`, + buildId, + applicationId + } + logs.push(log); + if (debug) { + await saveBuildLog(log); + } + } + } + }); + subprocess.on('exit', async (code) => { + if (code === 0) { + resolve(code); + } else { + if (!debug) { + for (const log of logs) { + await saveBuildLog(log); + } + } + reject(code); + } + }); + }) + } else { if (shell) { - subprocess = execaCommand(command, { + return await execaCommand(command, { env: { DOCKER_BUILDKIT: '1', DOCKER_HOST: engine } }); } else { - subprocess = execa(dockerCommand, dockerArgs, { + return await execa(dockerCommand, dockerArgs, { env: { DOCKER_BUILDKIT: '1', DOCKER_HOST: engine } }); } - const logs = []; - subprocess.stdout.on('data', async (data) => { - const stdout = data.toString(); - const array = stdout.split('\n'); - for (const line of array) { - if (line !== '\n' && line !== '') { - const log = { - line: `${line.replace('\n', '')}`, - buildId, - applicationId - } - logs.push(log); - if (debug) { - await saveBuildLog(log); - } - } - } - }); - subprocess.stderr.on('data', async (data) => { - const stderr = data.toString(); - const array = stderr.split('\n'); - for (const line of array) { - if (line !== '\n' && line !== '') { - const log = { - line: `${line.replace('\n', '')}`, - buildId, - applicationId - } - logs.push(log); - if (debug) { - await saveBuildLog(log); - } - } - } - }); - subprocess.on('exit', async (code) => { - await asyncSleep(1000); - if (code === 0) { - resolve(code); - } else { - if (!debug) { - for (const log of logs) { - await saveBuildLog(log); - } - } - reject(code); - } - }); - }) + } + } else { if (shell) { return execaCommand(command, { shell: true }); @@ -636,44 +648,7 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa return await execa(dockerCommand, dockerArgs); } } -export async function executeSSHCmd({ dockerId, command }) { - const { execaCommand, execa } = await import('execa') - const { parse } = await import('shell-quote') - let { remoteEngine, remoteIpAddress } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } }) - if (remoteEngine) { - await createRemoteEngineConfiguration(dockerId) - } - if (process.env.CODESANDBOX_HOST) { - if (command.startsWith('docker compose')) { - command = command.replace(/docker compose/gi, 'docker-compose') - } - } - const dockerArgs = parse(command); - return await execa('ssh', [`${remoteIpAddress}-remote`, ...dockerArgs]); -} -export async function executeDockerCmd({ debug, buildId, applicationId, dockerId, command }: { debug?: boolean, buildId?: string, applicationId?: string, dockerId: string, command: string }): Promise { - const { execa } = await import('execa') - const { parse } = await import('shell-quote') - let { remoteEngine, remoteIpAddress, engine } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } }) - if (remoteEngine) { - await createRemoteEngineConfiguration(dockerId); - engine = `ssh://${remoteIpAddress}-remote`; - } else { - engine = 'unix:///var/run/docker.sock'; - } - if (process.env.CODESANDBOX_HOST) { - if (command.startsWith('docker compose')) { - command = command.replace(/docker compose/gi, 'docker-compose'); - } - } - const parsedCommand = parse(command); - const dockerCommand = parsedCommand[0]; - const dockerArgs = parsedCommand.slice(1); - if (command.startsWith(`docker build`) || command.startsWith(`pack build`) || command.startsWith(`docker compose build`)) { - return await asyncExecShellStream({ debug, buildId, applicationId, command, engine }); - } - return await execa(dockerCommand, dockerArgs, { env: { DOCKER_BUILDKIT: "1", DOCKER_HOST: engine } }); -} + export async function startTraefikProxy(id: string): Promise { const { engine, network, remoteEngine, remoteIpAddress } = await prisma.destinationDocker.findUnique({ where: { id } }) const { found } = await checkContainer({ dockerId: id, container: 'coolify-proxy', remove: true }); diff --git a/apps/api/src/lib/importers/github.ts b/apps/api/src/lib/importers/github.ts index 774752b32..1313b77c5 100644 --- a/apps/api/src/lib/importers/github.ts +++ b/apps/api/src/lib/importers/github.ts @@ -32,13 +32,13 @@ export default async function ({ const url = htmlUrl.replace('https://', '').replace('http://', ''); if (forPublic) { await saveBuildLog({ - line: `Cloning ${repository}:${branch} branch`, + line: `Cloning ${repository}:${branch}...`, buildId, applicationId }); if (gitCommitHash) { await saveBuildLog({ - line: `Checking out ${gitCommitHash} commit`, + line: `Checking out ${gitCommitHash} commit...`, buildId, applicationId }); @@ -72,13 +72,13 @@ export default async function ({ }) .json(); await saveBuildLog({ - line: `Cloning ${repository}:${branch} branch`, + line: `Cloning ${repository}:${branch}...`, buildId, applicationId }); if (gitCommitHash) { await saveBuildLog({ - line: `Checking out ${gitCommitHash} commit`, + line: `Checking out ${gitCommitHash} commit...`, buildId, applicationId }); @@ -90,6 +90,5 @@ export default async function ({ }); } const { stdout: commit } = await executeCommand({ command: `cd ${workdir}/ && git rev-parse HEAD`, shell: true }); - console.log({ commit }) return commit.replace('\n', ''); } diff --git a/apps/api/src/lib/importers/gitlab.ts b/apps/api/src/lib/importers/gitlab.ts index 525ca9703..eef9b62ef 100644 --- a/apps/api/src/lib/importers/gitlab.ts +++ b/apps/api/src/lib/importers/gitlab.ts @@ -1,5 +1,5 @@ import { saveBuildLog } from "../buildPacks/common"; -import { executeCommand } from "../common"; +import { executeCommand } from "../common"; export default async function ({ applicationId, @@ -33,13 +33,13 @@ export default async function ({ } await saveBuildLog({ - line: `Cloning ${repository}:${branch} branch`, + line: `Cloning ${repository}:${branch}...`, buildId, applicationId }); if (gitCommitHash) { await saveBuildLog({ - line: `Checking out ${gitCommitHash} commit`, + line: `Checking out ${gitCommitHash} commit...`, buildId, applicationId }); diff --git a/apps/api/src/routes/api/v1/destinations/handlers.ts b/apps/api/src/routes/api/v1/destinations/handlers.ts index c4bcf71f5..e376d33ea 100644 --- a/apps/api/src/routes/api/v1/destinations/handlers.ts +++ b/apps/api/src/routes/api/v1/destinations/handlers.ts @@ -4,7 +4,7 @@ import sshConfig from 'ssh-config' import fs from 'fs/promises' import os from 'os'; -import { createRemoteEngineConfiguration, decrypt, errorHandler, executeCommand, executeSSHCmd, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common'; +import { createRemoteEngineConfiguration, decrypt, errorHandler, executeCommand, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common'; import { checkContainer } from '../../../../lib/docker'; import type { OnlyId } from '../../../../types'; @@ -216,7 +216,7 @@ export async function verifyRemoteDockerEngineFn(id: string) { } if (isCoolifyProxyUsed) await startTraefikProxy(id); try { - const { stdout: daemonJson } = await executeSSHCmd({ dockerId: id, command: `cat /etc/docker/daemon.json` }); + const { stdout: daemonJson } = await executeCommand({ sshCommand: true, dockerId: id, command: `cat /etc/docker/daemon.json` }); let daemonJsonParsed = JSON.parse(daemonJson); let isUpdated = false; if (!daemonJsonParsed['live-restore'] || daemonJsonParsed['live-restore'] !== true) { @@ -231,8 +231,8 @@ export async function verifyRemoteDockerEngineFn(id: string) { } } if (isUpdated) { - await executeSSHCmd({ dockerId: id, command: `echo '${JSON.stringify(daemonJsonParsed)}' > /etc/docker/daemon.json` }); - await executeSSHCmd({ dockerId: id, command: `systemctl restart docker` }); + await executeCommand({ sshCommand: true, shell: true, dockerId: id, command: `echo '${JSON.stringify(daemonJsonParsed)}' > /etc/docker/daemon.json` }); + await executeCommand({ sshCommand: true, dockerId: id, command: `systemctl restart docker` }); } } catch (error) { const daemonJsonParsed = { @@ -241,8 +241,8 @@ export async function verifyRemoteDockerEngineFn(id: string) { "buildkit": true } } - await executeSSHCmd({ dockerId: id, command: `echo '${JSON.stringify(daemonJsonParsed)}' > /etc/docker/daemon.json` }); - await executeSSHCmd({ dockerId: id, command: `systemctl restart docker` }); + await executeCommand({ sshCommand: true, shell: true, dockerId: id, command: `echo '${JSON.stringify(daemonJsonParsed)}' > /etc/docker/daemon.json` }); + await executeCommand({ sshCommand: true, dockerId: id, command: `systemctl restart docker` }); } finally { await prisma.destinationDocker.update({ where: { id }, data: { remoteVerified: true } }) } diff --git a/apps/api/src/routes/api/v1/handlers.ts b/apps/api/src/routes/api/v1/handlers.ts index 01686f5cb..072de0abc 100644 --- a/apps/api/src/routes/api/v1/handlers.ts +++ b/apps/api/src/routes/api/v1/handlers.ts @@ -13,7 +13,6 @@ import { uniqueName, version, sentryDSN, - executeDockerCmd, executeCommand, } from "../../../lib/common"; import { scheduler } from "../../../lib/scheduler"; diff --git a/apps/api/src/routes/api/v1/servers/handlers.ts b/apps/api/src/routes/api/v1/servers/handlers.ts index f05c2b965..24437181f 100644 --- a/apps/api/src/routes/api/v1/servers/handlers.ts +++ b/apps/api/src/routes/api/v1/servers/handlers.ts @@ -1,5 +1,5 @@ import type { FastifyRequest } from 'fastify'; -import { errorHandler, prisma, executeSSHCmd } from '../../../../lib/common'; +import { errorHandler, prisma, executeCommand } from '../../../../lib/common'; import os from 'node:os'; import osu from 'node-os-utils'; @@ -71,10 +71,10 @@ export async function showUsage(request: FastifyRequest) { let { remoteEngine } = request.query remoteEngine = remoteEngine === 'true' ? true : false if (remoteEngine) { - const { stdout: stats } = await executeSSHCmd({ dockerId: id, command: `vmstat -s` }) - const { stdout: disks } = await executeSSHCmd({ dockerId: id, command: `df -m / --output=size,used,pcent|grep -v 'Used'| xargs` }) - const { stdout: cpus } = await executeSSHCmd({ dockerId: id, command: `nproc --all` }) - const { stdout: cpuUsage } = await executeSSHCmd({ dockerId: id, command: `echo $[100-$(vmstat 1 2|tail -1|awk '{print $15}')]` }) + const { stdout: stats } = await executeCommand({ sshCommand: true, shell: true, dockerId: id, command: `vmstat -s` }) + const { stdout: disks } = await executeCommand({ sshCommand: true, shell: true, dockerId: id, command: `df -m / --output=size,used,pcent|grep -v 'Used'| xargs` }) + const { stdout: cpus } = await executeCommand({ sshCommand: true, shell: true, dockerId: id, command: `nproc --all` }) + const { stdout: cpuUsage } = await executeCommand({ sshCommand: true, shell: true, dockerId: id, command: `echo $[100-$(vmstat 1 2|tail -1|awk '{print $15}')]` }) const parsed: any = parseFromText(stats) return { usage: { diff --git a/apps/api/src/routes/api/v1/services/handlers.ts b/apps/api/src/routes/api/v1/services/handlers.ts index 88c027051..32333afc5 100644 --- a/apps/api/src/routes/api/v1/services/handlers.ts +++ b/apps/api/src/routes/api/v1/services/handlers.ts @@ -83,53 +83,56 @@ export async function getServiceStatus(request: FastifyRequest) { command: `docker ps -a --filter "label=com.docker.compose.project=${id}" --format '{{json .}}'` }); - const containersArray = containers.trim().split('\n'); - if (containersArray.length > 0 && containersArray[0] !== '') { - const templates = await getTemplates(); - let template = templates.find(t => t.type === service.type); - const templateStr = JSON.stringify(template) - if (templateStr) { - template = JSON.parse(templateStr.replaceAll('$$id', service.id)); - } - for (const container of containersArray) { - let isRunning = false; - let isExited = false; - let isRestarting = false; - let isExcluded = false; - const containerObj = JSON.parse(container); - const exclude = template?.services[containerObj.Names]?.exclude; - if (exclude) { + if (containers) { + const containersArray = containers.trim().split('\n'); + if (containersArray.length > 0 && containersArray[0] !== '') { + const templates = await getTemplates(); + let template = templates.find(t => t.type === service.type); + const templateStr = JSON.stringify(template) + if (templateStr) { + template = JSON.parse(templateStr.replaceAll('$$id', service.id)); + } + for (const container of containersArray) { + let isRunning = false; + let isExited = false; + let isRestarting = false; + let isExcluded = false; + const containerObj = JSON.parse(container); + const exclude = template?.services[containerObj.Names]?.exclude; + if (exclude) { + payload[containerObj.Names] = { + status: { + isExcluded: true, + isRunning: false, + isExited: false, + isRestarting: false, + } + } + continue; + } + + const status = containerObj.State + if (status === 'running') { + isRunning = true; + } + if (status === 'exited') { + isExited = true; + } + if (status === 'restarting') { + isRestarting = true; + } payload[containerObj.Names] = { status: { - isExcluded: true, - isRunning: false, - isExited: false, - isRestarting: false, + isExcluded, + isRunning, + isExited, + isRestarting } } - continue; - } - - const status = containerObj.State - if (status === 'running') { - isRunning = true; - } - if (status === 'exited') { - isExited = true; - } - if (status === 'restarting') { - isRestarting = true; - } - payload[containerObj.Names] = { - status: { - isExcluded, - isRunning, - isExited, - isRestarting - } } } } + } return payload } catch ({ status, message }) { diff --git a/apps/ui/src/routes/applications/[id]/__layout.svelte b/apps/ui/src/routes/applications/[id]/__layout.svelte index c839fe364..f9e8ff1ff 100644 --- a/apps/ui/src/routes/applications/[id]/__layout.svelte +++ b/apps/ui/src/routes/applications/[id]/__layout.svelte @@ -167,7 +167,8 @@ } } async function getStatus() { - if (($status.application.loading && stopping) || $status.application.restarting === true) return; + if (($status.application.loading && stopping) || $status.application.restarting === true) + return; $status.application.loading = true; const data = await get(`/applications/${id}/status`); @@ -453,7 +454,7 @@