From 86f1bf31b811d5193e27cf583025626ba3c2e31a Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Mon, 9 Sep 2024 23:46:24 -0600 Subject: [PATCH] feat: add reload, stop and start in remote server --- .../advanced/traefik/show-traefik-config.tsx | 11 +++-- .../application/domains/add-domain.tsx | 6 +-- apps/dokploy/pages/api/teapot.ts | 18 ++++++++ apps/dokploy/pages/hola.tsx | 3 ++ apps/dokploy/server/api/root.ts | 1 + .../dokploy/server/api/routers/application.ts | 42 +++++++++++++++---- apps/dokploy/server/api/routers/mariadb.ts | 34 +++++++++++---- apps/dokploy/server/api/routers/mongo.ts | 29 +++++++++++-- apps/dokploy/server/api/routers/mysql.ts | 27 ++++++++++-- apps/dokploy/server/api/routers/postgres.ts | 28 +++++++++++-- apps/dokploy/server/api/routers/redis.ts | 33 ++++++++++++--- .../server/api/services/application.ts | 1 - apps/dokploy/server/utils/docker/utils.ts | 20 ++++++++- .../server/utils/traefik/application.ts | 13 ++++++ 14 files changed, 224 insertions(+), 42 deletions(-) create mode 100644 apps/dokploy/pages/api/teapot.ts create mode 100644 apps/dokploy/pages/hola.tsx diff --git a/apps/dokploy/components/dashboard/application/advanced/traefik/show-traefik-config.tsx b/apps/dokploy/components/dashboard/application/advanced/traefik/show-traefik-config.tsx index bf5fd4f6..fb6fc0c1 100644 --- a/apps/dokploy/components/dashboard/application/advanced/traefik/show-traefik-config.tsx +++ b/apps/dokploy/components/dashboard/application/advanced/traefik/show-traefik-config.tsx @@ -7,7 +7,7 @@ import { CardTitle, } from "@/components/ui/card"; import { api } from "@/utils/api"; -import { File } from "lucide-react"; +import { File, Loader2 } from "lucide-react"; import React from "react"; import { UpdateTraefikConfig } from "./update-traefik-config"; interface Props { @@ -15,7 +15,7 @@ interface Props { } export const ShowTraefikConfig = ({ applicationId }: Props) => { - const { data } = api.application.readTraefikConfig.useQuery( + const { data, isLoading } = api.application.readTraefikConfig.useQuery( { applicationId, }, @@ -35,7 +35,12 @@ export const ShowTraefikConfig = ({ applicationId }: Props) => { - {data === null ? ( + {isLoading ? ( + + Loading... + + + ) : !data ? (
diff --git a/apps/dokploy/components/dashboard/application/domains/add-domain.tsx b/apps/dokploy/components/dashboard/application/domains/add-domain.tsx index 3f7edb4b..af6dd033 100644 --- a/apps/dokploy/components/dashboard/application/domains/add-domain.tsx +++ b/apps/dokploy/components/dashboard/application/domains/add-domain.tsx @@ -298,11 +298,7 @@ export const AddDomain = ({ - diff --git a/apps/dokploy/pages/api/teapot.ts b/apps/dokploy/pages/api/teapot.ts new file mode 100644 index 00000000..7485fa79 --- /dev/null +++ b/apps/dokploy/pages/api/teapot.ts @@ -0,0 +1,18 @@ +import type { NextRequest } from "next/server"; +import { renderToString } from "react-dom/server"; +import Page418 from "../hola"; // Importa la página 418 + +export const GET = async (req: NextRequest) => { + // Renderiza el componente de la página 418 como HTML + const htmlContent = renderToString(Page418()); + + // Devuelve la respuesta con el código de estado HTTP 418 + return new Response(htmlContent, { + headers: { + "Content-Type": "text/html", + }, + status: 418, + }); +}; + +export default GET; diff --git a/apps/dokploy/pages/hola.tsx b/apps/dokploy/pages/hola.tsx new file mode 100644 index 00000000..65b3d1aa --- /dev/null +++ b/apps/dokploy/pages/hola.tsx @@ -0,0 +1,3 @@ +export default function hola() { + return
hola
; +} diff --git a/apps/dokploy/server/api/root.ts b/apps/dokploy/server/api/root.ts index 025538fe..b82af907 100644 --- a/apps/dokploy/server/api/root.ts +++ b/apps/dokploy/server/api/root.ts @@ -36,6 +36,7 @@ import { serverRouter } from "./routers/server"; * * All routers added in /api/routers should be manually added here. */ + export const appRouter = createTRPCRouter({ admin: adminRouter, docker: dockerRouter, diff --git a/apps/dokploy/server/api/routers/application.ts b/apps/dokploy/server/api/routers/application.ts index 67e67099..42325c0d 100644 --- a/apps/dokploy/server/api/routers/application.ts +++ b/apps/dokploy/server/api/routers/application.ts @@ -27,7 +27,9 @@ import { enqueueDeploymentJob, myQueue } from "@/server/queues/queueSetup"; import { removeService, startService, + startServiceRemote, stopService, + stopServiceRemote, } from "@/server/utils/docker/utils"; import { removeDirectoryCode, @@ -38,6 +40,7 @@ import { readRemoteConfig, removeTraefikConfig, writeConfig, + writeConfigRemote, } from "@/server/utils/traefik/application"; import { deleteAllMiddlewares } from "@/server/utils/traefik/middleware"; import { TRPCError } from "@trpc/server"; @@ -53,7 +56,6 @@ import { } from "../services/application"; import { removeDeployments } from "../services/deployment"; import { addNewService, checkServiceAccess } from "../services/user"; - import { unzipDrop } from "@/server/utils/builders/drop"; import { uploadFileSchema } from "@/utils/schema"; @@ -97,9 +99,19 @@ export const applicationRouter = createTRPCRouter({ reload: protectedProcedure .input(apiReloadApplication) .mutation(async ({ input }) => { - await stopService(input.appName); + const application = await findApplicationById(input.applicationId); + if (application.serverId) { + await stopServiceRemote(application.serverId, input.appName); + } else { + await stopService(input.appName); + } await updateApplicationStatus(input.applicationId, "idle"); - await startService(input.appName); + + if (application.serverId) { + await startServiceRemote(application.serverId, input.appName); + } else { + await startService(input.appName); + } await updateApplicationStatus(input.applicationId, "done"); return true; }), @@ -143,7 +155,11 @@ export const applicationRouter = createTRPCRouter({ .input(apiFindOneApplication) .mutation(async ({ input }) => { const service = await findApplicationById(input.applicationId); - await stopService(service.appName); + if (service.serverId) { + await stopServiceRemote(service.serverId, service.appName); + } else { + await stopService(service.appName); + } await updateApplicationStatus(input.applicationId, "idle"); return service; @@ -153,8 +169,11 @@ export const applicationRouter = createTRPCRouter({ .input(apiFindOneApplication) .mutation(async ({ input }) => { const service = await findApplicationById(input.applicationId); - - await startService(service.appName); + if (service.serverId) { + await startServiceRemote(service.serverId, service.appName); + } else { + await startService(service.appName); + } await updateApplicationStatus(input.applicationId, "done"); return service; @@ -387,7 +406,16 @@ export const applicationRouter = createTRPCRouter({ .input(z.object({ applicationId: z.string(), traefikConfig: z.string() })) .mutation(async ({ input }) => { const application = await findApplicationById(input.applicationId); - writeConfig(application.appName, input.traefikConfig); + + if (application.serverId) { + await writeConfigRemote( + application.serverId, + application.appName, + input.traefikConfig, + ); + } else { + writeConfig(application.appName, input.traefikConfig); + } return true; }), readAppMonitoring: protectedProcedure diff --git a/apps/dokploy/server/api/routers/mariadb.ts b/apps/dokploy/server/api/routers/mariadb.ts index dc13461a..db35a18b 100644 --- a/apps/dokploy/server/api/routers/mariadb.ts +++ b/apps/dokploy/server/api/routers/mariadb.ts @@ -12,7 +12,9 @@ import { import { removeService, startService, + startServiceRemote, stopService, + stopServiceRemote, } from "@/server/utils/docker/utils"; import { TRPCError } from "@trpc/server"; import { @@ -72,8 +74,11 @@ export const mariadbRouter = createTRPCRouter({ .input(apiFindOneMariaDB) .mutation(async ({ input }) => { const service = await findMariadbById(input.mariadbId); - - await startService(service.appName); + if (service.serverId) { + await startServiceRemote(service.serverId, service.appName); + } else { + await startService(service.appName); + } await updateMariadbById(input.mariadbId, { applicationStatus: "done", }); @@ -83,13 +88,18 @@ export const mariadbRouter = createTRPCRouter({ stop: protectedProcedure .input(apiFindOneMariaDB) .mutation(async ({ input }) => { - const mongo = await findMariadbById(input.mariadbId); - await stopService(mongo.appName); + const mariadb = await findMariadbById(input.mariadbId); + + if (mariadb.serverId) { + await stopServiceRemote(mariadb.serverId, mariadb.appName); + } else { + await stopService(mariadb.appName); + } await updateMariadbById(input.mariadbId, { applicationStatus: "idle", }); - return mongo; + return mariadb; }), saveExternalPort: protectedProcedure .input(apiSaveExternalPortMariaDB) @@ -156,11 +166,21 @@ export const mariadbRouter = createTRPCRouter({ reload: protectedProcedure .input(apiResetMariadb) .mutation(async ({ input }) => { - await stopService(input.appName); + const mariadb = await findMariadbById(input.mariadbId); + if (mariadb.serverId) { + await stopServiceRemote(mariadb.serverId, mariadb.appName); + } else { + await stopService(mariadb.appName); + } await updateMariadbById(input.mariadbId, { applicationStatus: "idle", }); - await startService(input.appName); + + if (mariadb.serverId) { + await startServiceRemote(mariadb.serverId, mariadb.appName); + } else { + await startService(mariadb.appName); + } await updateMariadbById(input.mariadbId, { applicationStatus: "done", }); diff --git a/apps/dokploy/server/api/routers/mongo.ts b/apps/dokploy/server/api/routers/mongo.ts index e38ea749..152dc3d1 100644 --- a/apps/dokploy/server/api/routers/mongo.ts +++ b/apps/dokploy/server/api/routers/mongo.ts @@ -12,7 +12,9 @@ import { import { removeService, startService, + startServiceRemote, stopService, + stopServiceRemote, } from "@/server/utils/docker/utils"; import { TRPCError } from "@trpc/server"; import { @@ -74,7 +76,11 @@ export const mongoRouter = createTRPCRouter({ .mutation(async ({ input }) => { const service = await findMongoById(input.mongoId); - await startService(service.appName); + if (service.serverId) { + await startServiceRemote(service.serverId, service.appName); + } else { + await startService(service.appName); + } await updateMongoById(input.mongoId, { applicationStatus: "done", }); @@ -85,7 +91,12 @@ export const mongoRouter = createTRPCRouter({ .input(apiFindOneMongo) .mutation(async ({ input }) => { const mongo = await findMongoById(input.mongoId); - await stopService(mongo.appName); + + if (mongo.serverId) { + await stopServiceRemote(mongo.serverId, mongo.appName); + } else { + await stopService(mongo.appName); + } await updateMongoById(input.mongoId, { applicationStatus: "idle", }); @@ -119,11 +130,21 @@ export const mongoRouter = createTRPCRouter({ reload: protectedProcedure .input(apiResetMongo) .mutation(async ({ input }) => { - await stopService(input.appName); + const mongo = await findMongoById(input.mongoId); + if (mongo.serverId) { + await stopServiceRemote(mongo.serverId, mongo.appName); + } else { + await stopService(mongo.appName); + } await updateMongoById(input.mongoId, { applicationStatus: "idle", }); - await startService(input.appName); + + if (mongo.serverId) { + await startServiceRemote(mongo.serverId, mongo.appName); + } else { + await startService(mongo.appName); + } await updateMongoById(input.mongoId, { applicationStatus: "done", }); diff --git a/apps/dokploy/server/api/routers/mysql.ts b/apps/dokploy/server/api/routers/mysql.ts index 6be9af5f..9cd0fdd4 100644 --- a/apps/dokploy/server/api/routers/mysql.ts +++ b/apps/dokploy/server/api/routers/mysql.ts @@ -12,7 +12,9 @@ import { import { removeService, startService, + startServiceRemote, stopService, + stopServiceRemote, } from "@/server/utils/docker/utils"; import { TRPCError } from "@trpc/server"; import { createMount } from "../services/mount"; @@ -73,7 +75,11 @@ export const mysqlRouter = createTRPCRouter({ .mutation(async ({ input }) => { const service = await findMySqlById(input.mysqlId); - await startService(service.appName); + if (service.serverId) { + await startServiceRemote(service.serverId, service.appName); + } else { + await startService(service.appName); + } await updateMySqlById(input.mysqlId, { applicationStatus: "done", }); @@ -84,7 +90,11 @@ export const mysqlRouter = createTRPCRouter({ .input(apiFindOneMySql) .mutation(async ({ input }) => { const mongo = await findMySqlById(input.mysqlId); - await stopService(mongo.appName); + if (mongo.serverId) { + await stopServiceRemote(mongo.serverId, mongo.appName); + } else { + await stopService(mongo.appName); + } await updateMySqlById(input.mysqlId, { applicationStatus: "idle", }); @@ -118,11 +128,20 @@ export const mysqlRouter = createTRPCRouter({ reload: protectedProcedure .input(apiResetMysql) .mutation(async ({ input }) => { - await stopService(input.appName); + const mysql = await findMySqlById(input.mysqlId); + if (mysql.serverId) { + await stopServiceRemote(mysql.serverId, mysql.appName); + } else { + await stopService(mysql.appName); + } await updateMySqlById(input.mysqlId, { applicationStatus: "idle", }); - await startService(input.appName); + if (mysql.serverId) { + await startServiceRemote(mysql.serverId, mysql.appName); + } else { + await startService(mysql.appName); + } await updateMySqlById(input.mysqlId, { applicationStatus: "done", }); diff --git a/apps/dokploy/server/api/routers/postgres.ts b/apps/dokploy/server/api/routers/postgres.ts index a52074e0..69658381 100644 --- a/apps/dokploy/server/api/routers/postgres.ts +++ b/apps/dokploy/server/api/routers/postgres.ts @@ -12,7 +12,9 @@ import { import { removeService, startService, + startServiceRemote, stopService, + stopServiceRemote, } from "@/server/utils/docker/utils"; import { TRPCError } from "@trpc/server"; import { createMount } from "../services/mount"; @@ -74,7 +76,11 @@ export const postgresRouter = createTRPCRouter({ .mutation(async ({ input }) => { const service = await findPostgresById(input.postgresId); - await startService(service.appName); + if (service.serverId) { + await startServiceRemote(service.serverId, service.appName); + } else { + await startService(service.appName); + } await updatePostgresById(input.postgresId, { applicationStatus: "done", }); @@ -85,7 +91,11 @@ export const postgresRouter = createTRPCRouter({ .input(apiFindOnePostgres) .mutation(async ({ input }) => { const postgres = await findPostgresById(input.postgresId); - await stopService(postgres.appName); + if (postgres.serverId) { + await stopServiceRemote(postgres.serverId, postgres.appName); + } else { + await stopService(postgres.appName); + } await updatePostgresById(input.postgresId, { applicationStatus: "idle", }); @@ -152,11 +162,21 @@ export const postgresRouter = createTRPCRouter({ reload: protectedProcedure .input(apiResetPostgres) .mutation(async ({ input }) => { - await stopService(input.appName); + const postgres = await findPostgresById(input.postgresId); + if (postgres.serverId) { + await stopServiceRemote(postgres.serverId, postgres.appName); + } else { + await stopService(postgres.appName); + } await updatePostgresById(input.postgresId, { applicationStatus: "idle", }); - await startService(input.appName); + + if (postgres.serverId) { + await startServiceRemote(postgres.serverId, postgres.appName); + } else { + await startService(postgres.appName); + } await updatePostgresById(input.postgresId, { applicationStatus: "done", }); diff --git a/apps/dokploy/server/api/routers/redis.ts b/apps/dokploy/server/api/routers/redis.ts index 27bf391a..c52d8385 100644 --- a/apps/dokploy/server/api/routers/redis.ts +++ b/apps/dokploy/server/api/routers/redis.ts @@ -12,7 +12,9 @@ import { import { removeService, startService, + startServiceRemote, stopService, + stopServiceRemote, } from "@/server/utils/docker/utils"; import { TRPCError } from "@trpc/server"; import { createMount } from "../services/mount"; @@ -69,7 +71,12 @@ export const redisRouter = createTRPCRouter({ .input(apiFindOneRedis) .mutation(async ({ input }) => { const redis = await findRedisById(input.redisId); - await startService(redis.appName); + + if (redis.serverId) { + await startServiceRemote(redis.serverId, redis.appName); + } else { + await startService(redis.appName); + } await updateRedisById(input.redisId, { applicationStatus: "done", }); @@ -79,11 +86,21 @@ export const redisRouter = createTRPCRouter({ reload: protectedProcedure .input(apiResetRedis) .mutation(async ({ input }) => { - await stopService(input.appName); + const redis = await findRedisById(input.redisId); + if (redis.serverId) { + await stopServiceRemote(redis.serverId, redis.appName); + } else { + await stopService(redis.appName); + } await updateRedisById(input.redisId, { applicationStatus: "idle", }); - await startService(input.appName); + + if (redis.serverId) { + await startServiceRemote(redis.serverId, redis.appName); + } else { + await startService(redis.appName); + } await updateRedisById(input.redisId, { applicationStatus: "done", }); @@ -93,13 +110,17 @@ export const redisRouter = createTRPCRouter({ stop: protectedProcedure .input(apiFindOneRedis) .mutation(async ({ input }) => { - const mongo = await findRedisById(input.redisId); - await stopService(mongo.appName); + const redis = await findRedisById(input.redisId); + if (redis.serverId) { + await stopServiceRemote(redis.serverId, redis.appName); + } else { + await stopService(redis.appName); + } await updateRedisById(input.redisId, { applicationStatus: "idle", }); - return mongo; + return redis; }), saveExternalPort: protectedProcedure .input(apiSaveExternalPortRedis) diff --git a/apps/dokploy/server/api/services/application.ts b/apps/dokploy/server/api/services/application.ts index 098837af..e815392b 100644 --- a/apps/dokploy/server/api/services/application.ts +++ b/apps/dokploy/server/api/services/application.ts @@ -169,7 +169,6 @@ export const deployApplication = async ({ `; if (application.sourceType === "github") { command += await getGithubCloneCommand(application, deployment.logPath); - console.log(application); command += getBuildCommand(application, deployment.logPath); } else if (application.sourceType === "gitlab") { command += await getGitlabCloneCommand(application, deployment.logPath); diff --git a/apps/dokploy/server/utils/docker/utils.ts b/apps/dokploy/server/utils/docker/utils.ts index 20a34859..146b010c 100644 --- a/apps/dokploy/server/utils/docker/utils.ts +++ b/apps/dokploy/server/utils/docker/utils.ts @@ -5,7 +5,7 @@ import { APPLICATIONS_PATH, docker } from "@/server/constants"; import type { ContainerInfo, ResourceRequirements } from "dockerode"; import { parse } from "dotenv"; import type { ApplicationNested } from "../builders"; -import { execAsync } from "../process/execAsync"; +import { execAsync, execAsyncRemote } from "../process/execAsync"; import { getRemoteDocker } from "../servers/remote-docker"; interface RegistryAuth { @@ -116,6 +116,15 @@ export const stopService = async (appName: string) => { } }; +export const stopServiceRemote = async (serverId: string, appName: string) => { + try { + await execAsyncRemote(serverId, `docker service scale ${appName}=0 `); + } catch (error) { + console.error(error); + return error; + } +}; + export const getContainerByName = (name: string): Promise => { const opts = { limit: 1, @@ -196,6 +205,15 @@ export const startService = async (appName: string) => { } }; +export const startServiceRemote = async (serverId: string, appName: string) => { + try { + await execAsyncRemote(serverId, `docker service scale ${appName}=1 `); + } catch (error) { + console.error(error); + throw error; + } +}; + export const removeService = async (appName: string) => { try { await execAsync(`docker service rm ${appName}`); diff --git a/apps/dokploy/server/utils/traefik/application.ts b/apps/dokploy/server/utils/traefik/application.ts index 5173be87..6c9fe70b 100644 --- a/apps/dokploy/server/utils/traefik/application.ts +++ b/apps/dokploy/server/utils/traefik/application.ts @@ -145,6 +145,19 @@ export const writeConfig = (appName: string, traefikConfig: string) => { } }; +export const writeConfigRemote = async ( + serverId: string, + appName: string, + traefikConfig: string, +) => { + try { + const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`); + await execAsyncRemote(serverId, `echo '${traefikConfig}' > ${configPath}`); + } catch (e) { + console.error("Error saving the YAML config file:", e); + } +}; + export const writeTraefikConfigInPath = ( pathFile: string, traefikConfig: string,