From 39f6fb5af3fdb3a19fb0f4effa9d46d0c38da96c Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Tue, 3 Sep 2024 01:24:06 -0600 Subject: [PATCH 1/7] feat(test): add test to prevent add hash to dokploy-network --- .../compose/network/network-root.test.ts | 52 +++++++++++ .../compose/network/network-service.test.ts | 89 +++++++++++++++++++ .../__test__/compose/network/network.test.ts | 79 ++++++++++++++++ .../server/utils/docker/compose/network.ts | 27 ++++-- 4 files changed, 239 insertions(+), 8 deletions(-) diff --git a/apps/dokploy/__test__/compose/network/network-root.test.ts b/apps/dokploy/__test__/compose/network/network-root.test.ts index b4a0929c..297f358f 100644 --- a/apps/dokploy/__test__/compose/network/network-root.test.ts +++ b/apps/dokploy/__test__/compose/network/network-root.test.ts @@ -279,3 +279,55 @@ test("Add prefix to networks with static prefix", () => { ) as ComposeSpecification; expect(networks).toStrictEqual(expectedComposeData.networks); }); + +const composeFile7 = ` +version: "3.8" + +services: + web: + image: nginx:latest + networks: + - dokploy-network + +networks: + dokploy-network: +`; + +const expectedComposeFile7 = ` +version: "3.8" + +services: + web: + image: nginx:latest + networks: + - dokploy-network + +networks: + dokploy-network: + driver: bridge + driver_opts: + com.docker.network.driver.mtu: 1200 + + backend: + driver: bridge + attachable: true + + external_network: + external: true + name: dokploy-network +`; +test("It shoudn't add prefix to dokploy-network", () => { + const composeData = load(composeFile7) as ComposeSpecification; + + const prefix = generateRandomHash(); + + if (!composeData?.networks) { + return; + } + const networks = addPrefixToNetworksRoot(composeData.networks, prefix); + + expect(networks).toBeDefined(); + for (const networkKey of Object.keys(networks)) { + expect(networkKey).toContain("dokploy-network"); + } +}); diff --git a/apps/dokploy/__test__/compose/network/network-service.test.ts b/apps/dokploy/__test__/compose/network/network-service.test.ts index d592811b..6f96c11d 100644 --- a/apps/dokploy/__test__/compose/network/network-service.test.ts +++ b/apps/dokploy/__test__/compose/network/network-service.test.ts @@ -182,3 +182,92 @@ test("Add prefix to networks in services (combined case)", () => { expect(redisNetworks).toHaveProperty(`backend-${prefix}`); expect(redisNetworks).not.toHaveProperty("backend"); }); + +const composeFile7 = ` +version: "3.8" + +services: + web: + image: nginx:latest + networks: + - dokploy-network +`; + +test("It shoudn't add prefix to dokploy-network in services", () => { + const composeData = load(composeFile7) as ComposeSpecification; + + const prefix = generateRandomHash(); + + if (!composeData?.services) { + return; + } + const networks = addPrefixToServiceNetworks(composeData.services, prefix); + const service = networks.web; + + expect(service).toBeDefined(); + expect(service?.networks).toContain("dokploy-network"); +}); + +const composeFile8 = ` +version: "3.8" + +services: + web: + image: nginx:latest + networks: + - frontend + - backend + - dokploy-network + + + api: + image: myapi:latest + networks: + frontend: + aliases: + - api + dokploy-network: + aliases: + - api + redis: + image: redis:alpine + networks: + dokploy-network: + db: + image: myapi:latest + networks: + dokploy-network: + aliases: + - apid + +`; + +test("It shoudn't add prefix to dokploy-network in services multiples cases", () => { + const composeData = load(composeFile8) as ComposeSpecification; + + const prefix = generateRandomHash(); + + if (!composeData?.services) { + return; + } + const networks = addPrefixToServiceNetworks(composeData.services, prefix); + const service = networks.web; + const api = networks.api; + const redis = networks.redis; + const db = networks.db; + + const dbNetworks = db?.networks as { + [key: string]: unknown; + }; + + const apiNetworks = api?.networks as { + [key: string]: unknown; + }; + + expect(service).toBeDefined(); + expect(service?.networks).toContain("dokploy-network"); + + expect(redis?.networks).toHaveProperty("dokploy-network"); + expect(dbNetworks["dokploy-network"]).toBeDefined(); + expect(apiNetworks["dokploy-network"]).toBeDefined(); +}); diff --git a/apps/dokploy/__test__/compose/network/network.test.ts b/apps/dokploy/__test__/compose/network/network.test.ts index f86cabfd..354fd650 100644 --- a/apps/dokploy/__test__/compose/network/network.test.ts +++ b/apps/dokploy/__test__/compose/network/network.test.ts @@ -254,3 +254,82 @@ test("Add prefix to networks in compose file with multiple services and complex expect(updatedComposeData).toEqual(expectedComposeFile3); }); + +const composeFile4 = ` +version: "3.8" + +services: + app: + image: myapp:latest + networks: + frontend: + aliases: + - app + backend: + dokploy-network: + + worker: + image: worker:latest + networks: + - backend + - dokploy-network + +networks: + frontend: + driver: bridge + attachable: true + + backend: + driver: bridge + driver_opts: + com.docker.network.bridge.enable_icc: "true" + + dokploy-network: + driver: bridge + +`; + +const expectedComposeFile4 = load(` +version: "3.8" + +services: + app: + image: myapp:latest + networks: + frontend-testhash: + aliases: + - app + backend-testhash: + dokploy-network: + + worker: + image: worker:latest + networks: + - backend-testhash + - dokploy-network + +networks: + frontend-testhash: + driver: bridge + attachable: true + + backend-testhash: + driver: bridge + driver_opts: + com.docker.network.bridge.enable_icc: "true" + + dokploy-network: + driver: bridge + + + +`); + +test("Expect don't add prefix to dokploy-network in compose file with multiple services and complex network configurations", () => { + const composeData = load(composeFile4) as ComposeSpecification; + + const prefix = "testhash"; + const updatedComposeData = addPrefixToAllNetworks(composeData, prefix); + console.log(updatedComposeData); + expect(updatedComposeData).toEqual(expectedComposeFile4); +}); diff --git a/apps/dokploy/server/utils/docker/compose/network.ts b/apps/dokploy/server/utils/docker/compose/network.ts index 39e9564f..c52f1368 100644 --- a/apps/dokploy/server/utils/docker/compose/network.ts +++ b/apps/dokploy/server/utils/docker/compose/network.ts @@ -9,7 +9,12 @@ export const addPrefixToNetworksRoot = ( networks: { [key: string]: DefinitionsNetwork }, prefix: string, ): { [key: string]: DefinitionsNetwork } => { - return _.mapKeys(networks, (_value, key) => `${key}-${prefix}`); + return _.mapKeys(networks, (_value, key) => { + if (key === "dokploy-network") { + return "dokploy-network"; + } + return `${key}-${prefix}`; + }); }; export const addPrefixToServiceNetworks = ( @@ -20,15 +25,20 @@ export const addPrefixToServiceNetworks = ( if (service.networks) { // 1 Case the most common if (Array.isArray(service.networks)) { - service.networks = service.networks.map( - (network: string) => `${network}-${prefix}`, - ); + service.networks = service.networks.map((network: string) => { + if (network === "dokploy-network") { + return "dokploy-network"; + } + return `${network}-${prefix}`; + }); } else { // 2 Case - service.networks = _.mapKeys( - service.networks, - (_value, key) => `${key}-${prefix}`, - ); + service.networks = _.mapKeys(service.networks, (_value, key) => { + if (key === "dokploy-network") { + return "dokploy-network"; + } + return `${key}-${prefix}`; + }); // 3 Case service.networks = _.mapValues(service.networks, (value) => { @@ -40,6 +50,7 @@ export const addPrefixToServiceNetworks = ( return `${innerKey}-${prefix}`; }); } + return value; }); } From a3be030fac85317e9639358bafeaed6da85ff2d0 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Tue, 3 Sep 2024 22:56:38 -0600 Subject: [PATCH 2/7] feat: add randomize compose by prefix --- .../compose/general/compose-file-editor.tsx | 29 +- .../compose/general/randomize-compose.tsx | 187 +- .../drizzle/0035_tired_kinsey_walden.sql | 2 + apps/dokploy/drizzle/meta/0035_snapshot.json | 3559 +++++++++++++++++ apps/dokploy/drizzle/meta/_journal.json | 7 + apps/dokploy/server/api/routers/compose.ts | 12 +- apps/dokploy/server/db/schema/compose.ts | 2 + apps/dokploy/server/utils/builders/compose.ts | 4 + apps/dokploy/server/utils/docker/compose.ts | 8 + apps/dokploy/server/utils/docker/domain.ts | 8 +- 10 files changed, 3776 insertions(+), 42 deletions(-) create mode 100644 apps/dokploy/drizzle/0035_tired_kinsey_walden.sql create mode 100644 apps/dokploy/drizzle/meta/0035_snapshot.json diff --git a/apps/dokploy/components/dashboard/compose/general/compose-file-editor.tsx b/apps/dokploy/components/dashboard/compose/general/compose-file-editor.tsx index bb896e9a..292ff4ca 100644 --- a/apps/dokploy/components/dashboard/compose/general/compose-file-editor.tsx +++ b/apps/dokploy/components/dashboard/compose/general/compose-file-editor.tsx @@ -83,9 +83,10 @@ export const ComposeFileEditor = ({ composeId }: Props) => { }; return ( <> -
+
@@ -121,21 +122,21 @@ services: )} /> - -
-
- -
- -
+
+
+ +
+ +
); diff --git a/apps/dokploy/components/dashboard/compose/general/randomize-compose.tsx b/apps/dokploy/components/dashboard/compose/general/randomize-compose.tsx index 977dd2f6..2fc59f12 100644 --- a/apps/dokploy/components/dashboard/compose/general/randomize-compose.tsx +++ b/apps/dokploy/components/dashboard/compose/general/randomize-compose.tsx @@ -1,5 +1,7 @@ import { AlertBlock } from "@/components/shared/alert-block"; +import { CodeEditor } from "@/components/shared/code-editor"; import { Button } from "@/components/ui/button"; +import { CardTitle } from "@/components/ui/card"; import { Dialog, DialogContent, @@ -8,25 +10,91 @@ import { DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; +import { + FormField, + FormItem, + FormLabel, + FormControl, + FormDescription, + FormMessage, + Form, +} from "@/components/ui/form"; import { Input } from "@/components/ui/input"; +import { + InputOTP, + InputOTPGroup, + InputOTPSlot, +} from "@/components/ui/input-otp"; +import { Switch } from "@/components/ui/switch"; import { api } from "@/utils/api"; -import { Dices } from "lucide-react"; -import { useState } from "react"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { AlertTriangle, Dices } from "lucide-react"; +import { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; import { toast } from "sonner"; +import { z } from "zod"; interface Props { composeId: string; } +const schema = z.object({ + prefix: z.string(), + randomize: z.boolean().optional(), +}); + +type Schema = z.infer; + export const RandomizeCompose = ({ composeId }: Props) => { const utils = api.useUtils(); - const [prefix, setPrefix] = useState(""); const [compose, setCompose] = useState(""); const [isOpen, setIsOpen] = useState(false); const { mutateAsync, error, isError } = api.compose.randomizeCompose.useMutation(); - const onSubmit = async () => { + const { mutateAsync: updateCompose } = api.compose.update.useMutation(); + + const { data, refetch } = api.compose.one.useQuery( + { composeId }, + { enabled: !!composeId }, + ); + + const form = useForm({ + defaultValues: { + prefix: "", + randomize: false, + }, + resolver: zodResolver(schema), + }); + + const prefix = form.watch("prefix"); + + useEffect(() => { + if (data) { + form.reset({ + prefix: data?.prefix || "", + randomize: data?.randomize || false, + }); + } + }, [form, form.reset, form.formState.isSubmitSuccessful, data]); + + const onSubmit = async (formData: Schema) => { + await updateCompose({ + composeId, + prefix: formData?.prefix || "", + randomize: formData?.randomize || false, + }) + .then(async (data) => { + randomizeCompose(); + refetch(); + toast.success("Compose updated"); + }) + .catch(() => { + toast.error("Error to randomize the compose"); + }); + }; + + const randomizeCompose = async () => { await mutateAsync({ composeId, prefix, @@ -43,7 +111,7 @@ export const RandomizeCompose = ({ composeId }: Props) => { return ( - onSubmit()}> + randomizeCompose()}>
-
- setPrefix(e.target.value)} - /> - + + When you activate this option, we will include a env + `COMPOSE_PREFIX` variable to the compose file so you can use it in + your compose file. +
{isError && {error?.message}} +
+ + {isError && ( +
+ + + {error?.message} + +
+ )} -
-
-						{compose}
-					
-
+
+
+ ( + + Prefix + + + + + + )} + /> + ( + +
+ Apply Randomize + + Apply randomize to the compose file. + +
+ + + +
+ )} + /> +
+ +
+ + +
+
+
+							
+						
+
+ ); diff --git a/apps/dokploy/drizzle/0035_tired_kinsey_walden.sql b/apps/dokploy/drizzle/0035_tired_kinsey_walden.sql new file mode 100644 index 00000000..b5ac9328 --- /dev/null +++ b/apps/dokploy/drizzle/0035_tired_kinsey_walden.sql @@ -0,0 +1,2 @@ +ALTER TABLE "compose" ADD COLUMN "prefix" text DEFAULT '' NOT NULL;--> statement-breakpoint +ALTER TABLE "compose" ADD COLUMN "randomize" boolean DEFAULT false NOT NULL; \ No newline at end of file diff --git a/apps/dokploy/drizzle/meta/0035_snapshot.json b/apps/dokploy/drizzle/meta/0035_snapshot.json new file mode 100644 index 00000000..80b4e4a8 --- /dev/null +++ b/apps/dokploy/drizzle/meta/0035_snapshot.json @@ -0,0 +1,3559 @@ +{ + "id": "51601bf9-6706-4a79-9029-cbad20ea9e02", + "prevId": "6a7ce86e-f628-4786-ab30-e160dcdb0a39", + "version": "6", + "dialect": "postgresql", + "tables": { + "public.application": { + "name": "application", + "schema": "", + "columns": { + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "buildArgs": { + "name": "buildArgs", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "subtitle": { + "name": "subtitle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refreshToken": { + "name": "refreshToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sourceType": { + "name": "sourceType", + "type": "sourceType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'github'" + }, + "repository": { + "name": "repository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner": { + "name": "owner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "buildPath": { + "name": "buildPath", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "autoDeploy": { + "name": "autoDeploy", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "gitlabProjectId": { + "name": "gitlabProjectId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "gitlabRepository": { + "name": "gitlabRepository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabOwner": { + "name": "gitlabOwner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabBranch": { + "name": "gitlabBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabBuildPath": { + "name": "gitlabBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "gitlabPathNamespace": { + "name": "gitlabPathNamespace", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketRepository": { + "name": "bitbucketRepository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketOwner": { + "name": "bitbucketOwner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketBranch": { + "name": "bitbucketBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketBuildPath": { + "name": "bitbucketBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitUrl": { + "name": "customGitUrl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitBranch": { + "name": "customGitBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitBuildPath": { + "name": "customGitBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitSSHKeyId": { + "name": "customGitSSHKeyId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerfile": { + "name": "dockerfile", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerContextPath": { + "name": "dockerContextPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerBuildStage": { + "name": "dockerBuildStage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dropBuildPath": { + "name": "dropBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "healthCheckSwarm": { + "name": "healthCheckSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "restartPolicySwarm": { + "name": "restartPolicySwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "placementSwarm": { + "name": "placementSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "updateConfigSwarm": { + "name": "updateConfigSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "rollbackConfigSwarm": { + "name": "rollbackConfigSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "modeSwarm": { + "name": "modeSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "labelsSwarm": { + "name": "labelsSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "networkSwarm": { + "name": "networkSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "replicas": { + "name": "replicas", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "buildType": { + "name": "buildType", + "type": "buildType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'nixpacks'" + }, + "publishDirectory": { + "name": "publishDirectory", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "registryId": { + "name": "registryId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "githubId": { + "name": "githubId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabId": { + "name": "gitlabId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketId": { + "name": "bitbucketId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "application_customGitSSHKeyId_ssh-key_sshKeyId_fk": { + "name": "application_customGitSSHKeyId_ssh-key_sshKeyId_fk", + "tableFrom": "application", + "tableTo": "ssh-key", + "columnsFrom": [ + "customGitSSHKeyId" + ], + "columnsTo": [ + "sshKeyId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_registryId_registry_registryId_fk": { + "name": "application_registryId_registry_registryId_fk", + "tableFrom": "application", + "tableTo": "registry", + "columnsFrom": [ + "registryId" + ], + "columnsTo": [ + "registryId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_projectId_project_projectId_fk": { + "name": "application_projectId_project_projectId_fk", + "tableFrom": "application", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "application_githubId_github_githubId_fk": { + "name": "application_githubId_github_githubId_fk", + "tableFrom": "application", + "tableTo": "github", + "columnsFrom": [ + "githubId" + ], + "columnsTo": [ + "githubId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_gitlabId_gitlab_gitlabId_fk": { + "name": "application_gitlabId_gitlab_gitlabId_fk", + "tableFrom": "application", + "tableTo": "gitlab", + "columnsFrom": [ + "gitlabId" + ], + "columnsTo": [ + "gitlabId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_bitbucketId_bitbucket_bitbucketId_fk": { + "name": "application_bitbucketId_bitbucket_bitbucketId_fk", + "tableFrom": "application", + "tableTo": "bitbucket", + "columnsFrom": [ + "bitbucketId" + ], + "columnsTo": [ + "bitbucketId" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "application_appName_unique": { + "name": "application_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.postgres": { + "name": "postgres", + "schema": "", + "columns": { + "postgresId": { + "name": "postgresId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseName": { + "name": "databaseName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "postgres_projectId_project_projectId_fk": { + "name": "postgres_projectId_project_projectId_fk", + "tableFrom": "postgres", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "postgres_appName_unique": { + "name": "postgres_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isRegistered": { + "name": "isRegistered", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "expirationDate": { + "name": "expirationDate", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "canCreateProjects": { + "name": "canCreateProjects", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToSSHKeys": { + "name": "canAccessToSSHKeys", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canCreateServices": { + "name": "canCreateServices", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canDeleteProjects": { + "name": "canDeleteProjects", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canDeleteServices": { + "name": "canDeleteServices", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToDocker": { + "name": "canAccessToDocker", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToAPI": { + "name": "canAccessToAPI", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToGitProviders": { + "name": "canAccessToGitProviders", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToTraefikFiles": { + "name": "canAccessToTraefikFiles", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "accesedProjects": { + "name": "accesedProjects", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "accesedServices": { + "name": "accesedServices", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "authId": { + "name": "authId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "user_adminId_admin_adminId_fk": { + "name": "user_adminId_admin_adminId_fk", + "tableFrom": "user", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_authId_auth_id_fk": { + "name": "user_authId_auth_id_fk", + "tableFrom": "user", + "tableTo": "auth", + "columnsFrom": [ + "authId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.admin": { + "name": "admin", + "schema": "", + "columns": { + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "serverIp": { + "name": "serverIp", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "certificateType": { + "name": "certificateType", + "type": "certificateType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "letsEncryptEmail": { + "name": "letsEncryptEmail", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sshPrivateKey": { + "name": "sshPrivateKey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enableDockerCleanup": { + "name": "enableDockerCleanup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "authId": { + "name": "authId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "admin_authId_auth_id_fk": { + "name": "admin_authId_auth_id_fk", + "tableFrom": "admin", + "tableTo": "auth", + "columnsFrom": [ + "authId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.auth": { + "name": "auth", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "rol": { + "name": "rol", + "type": "Roles", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is2FAEnabled": { + "name": "is2FAEnabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "auth_email_unique": { + "name": "auth_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "public.project": { + "name": "project", + "schema": "", + "columns": { + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "project_adminId_admin_adminId_fk": { + "name": "project_adminId_admin_adminId_fk", + "tableFrom": "project", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.domain": { + "name": "domain", + "schema": "", + "columns": { + "domainId": { + "name": "domainId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "https": { + "name": "https", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 3000 + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "serviceName": { + "name": "serviceName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "domainType": { + "name": "domainType", + "type": "domainType", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'application'" + }, + "uniqueConfigKey": { + "name": "uniqueConfigKey", + "type": "serial", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "certificateType": { + "name": "certificateType", + "type": "certificateType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + } + }, + "indexes": {}, + "foreignKeys": { + "domain_composeId_compose_composeId_fk": { + "name": "domain_composeId_compose_composeId_fk", + "tableFrom": "domain", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "domain_applicationId_application_applicationId_fk": { + "name": "domain_applicationId_application_applicationId_fk", + "tableFrom": "domain", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.mariadb": { + "name": "mariadb", + "schema": "", + "columns": { + "mariadbId": { + "name": "mariadbId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "databaseName": { + "name": "databaseName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "rootPassword": { + "name": "rootPassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mariadb_projectId_project_projectId_fk": { + "name": "mariadb_projectId_project_projectId_fk", + "tableFrom": "mariadb", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mariadb_appName_unique": { + "name": "mariadb_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.mongo": { + "name": "mongo", + "schema": "", + "columns": { + "mongoId": { + "name": "mongoId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mongo_projectId_project_projectId_fk": { + "name": "mongo_projectId_project_projectId_fk", + "tableFrom": "mongo", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mongo_appName_unique": { + "name": "mongo_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.mysql": { + "name": "mysql", + "schema": "", + "columns": { + "mysqlId": { + "name": "mysqlId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "databaseName": { + "name": "databaseName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "rootPassword": { + "name": "rootPassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mysql_projectId_project_projectId_fk": { + "name": "mysql_projectId_project_projectId_fk", + "tableFrom": "mysql", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mysql_appName_unique": { + "name": "mysql_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.backup": { + "name": "backup", + "schema": "", + "columns": { + "backupId": { + "name": "backupId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "schedule": { + "name": "schedule", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "destinationId": { + "name": "destinationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseType": { + "name": "databaseType", + "type": "databaseType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "postgresId": { + "name": "postgresId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mariadbId": { + "name": "mariadbId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mysqlId": { + "name": "mysqlId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mongoId": { + "name": "mongoId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "backup_destinationId_destination_destinationId_fk": { + "name": "backup_destinationId_destination_destinationId_fk", + "tableFrom": "backup", + "tableTo": "destination", + "columnsFrom": [ + "destinationId" + ], + "columnsTo": [ + "destinationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_postgresId_postgres_postgresId_fk": { + "name": "backup_postgresId_postgres_postgresId_fk", + "tableFrom": "backup", + "tableTo": "postgres", + "columnsFrom": [ + "postgresId" + ], + "columnsTo": [ + "postgresId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_mariadbId_mariadb_mariadbId_fk": { + "name": "backup_mariadbId_mariadb_mariadbId_fk", + "tableFrom": "backup", + "tableTo": "mariadb", + "columnsFrom": [ + "mariadbId" + ], + "columnsTo": [ + "mariadbId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_mysqlId_mysql_mysqlId_fk": { + "name": "backup_mysqlId_mysql_mysqlId_fk", + "tableFrom": "backup", + "tableTo": "mysql", + "columnsFrom": [ + "mysqlId" + ], + "columnsTo": [ + "mysqlId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_mongoId_mongo_mongoId_fk": { + "name": "backup_mongoId_mongo_mongoId_fk", + "tableFrom": "backup", + "tableTo": "mongo", + "columnsFrom": [ + "mongoId" + ], + "columnsTo": [ + "mongoId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.destination": { + "name": "destination", + "schema": "", + "columns": { + "destinationId": { + "name": "destinationId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accessKey": { + "name": "accessKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secretAccessKey": { + "name": "secretAccessKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "bucket": { + "name": "bucket", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "region": { + "name": "region", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "destination_adminId_admin_adminId_fk": { + "name": "destination_adminId_admin_adminId_fk", + "tableFrom": "destination", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment": { + "name": "deployment", + "schema": "", + "columns": { + "deploymentId": { + "name": "deploymentId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "deploymentStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'running'" + }, + "logPath": { + "name": "logPath", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_applicationId_application_applicationId_fk": { + "name": "deployment_applicationId_application_applicationId_fk", + "tableFrom": "deployment", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_composeId_compose_composeId_fk": { + "name": "deployment_composeId_compose_composeId_fk", + "tableFrom": "deployment", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.mount": { + "name": "mount", + "schema": "", + "columns": { + "mountId": { + "name": "mountId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "mountType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "hostPath": { + "name": "hostPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "volumeName": { + "name": "volumeName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "filePath": { + "name": "filePath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "serviceType": { + "name": "serviceType", + "type": "serviceType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'application'" + }, + "mountPath": { + "name": "mountPath", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "postgresId": { + "name": "postgresId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mariadbId": { + "name": "mariadbId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mongoId": { + "name": "mongoId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mysqlId": { + "name": "mysqlId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "redisId": { + "name": "redisId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "mount_applicationId_application_applicationId_fk": { + "name": "mount_applicationId_application_applicationId_fk", + "tableFrom": "mount", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_postgresId_postgres_postgresId_fk": { + "name": "mount_postgresId_postgres_postgresId_fk", + "tableFrom": "mount", + "tableTo": "postgres", + "columnsFrom": [ + "postgresId" + ], + "columnsTo": [ + "postgresId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_mariadbId_mariadb_mariadbId_fk": { + "name": "mount_mariadbId_mariadb_mariadbId_fk", + "tableFrom": "mount", + "tableTo": "mariadb", + "columnsFrom": [ + "mariadbId" + ], + "columnsTo": [ + "mariadbId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_mongoId_mongo_mongoId_fk": { + "name": "mount_mongoId_mongo_mongoId_fk", + "tableFrom": "mount", + "tableTo": "mongo", + "columnsFrom": [ + "mongoId" + ], + "columnsTo": [ + "mongoId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_mysqlId_mysql_mysqlId_fk": { + "name": "mount_mysqlId_mysql_mysqlId_fk", + "tableFrom": "mount", + "tableTo": "mysql", + "columnsFrom": [ + "mysqlId" + ], + "columnsTo": [ + "mysqlId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_redisId_redis_redisId_fk": { + "name": "mount_redisId_redis_redisId_fk", + "tableFrom": "mount", + "tableTo": "redis", + "columnsFrom": [ + "redisId" + ], + "columnsTo": [ + "redisId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_composeId_compose_composeId_fk": { + "name": "mount_composeId_compose_composeId_fk", + "tableFrom": "mount", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.certificate": { + "name": "certificate", + "schema": "", + "columns": { + "certificateId": { + "name": "certificateId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "certificateData": { + "name": "certificateData", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "privateKey": { + "name": "privateKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "certificatePath": { + "name": "certificatePath", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "autoRenew": { + "name": "autoRenew", + "type": "boolean", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "certificate_certificatePath_unique": { + "name": "certificate_certificatePath_unique", + "nullsNotDistinct": false, + "columns": [ + "certificatePath" + ] + } + } + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_auth_id_fk": { + "name": "session_user_id_auth_id_fk", + "tableFrom": "session", + "tableTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.redirect": { + "name": "redirect", + "schema": "", + "columns": { + "redirectId": { + "name": "redirectId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "regex": { + "name": "regex", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "replacement": { + "name": "replacement", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permanent": { + "name": "permanent", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "uniqueConfigKey": { + "name": "uniqueConfigKey", + "type": "serial", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "redirect_applicationId_application_applicationId_fk": { + "name": "redirect_applicationId_application_applicationId_fk", + "tableFrom": "redirect", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.security": { + "name": "security", + "schema": "", + "columns": { + "securityId": { + "name": "securityId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "security_applicationId_application_applicationId_fk": { + "name": "security_applicationId_application_applicationId_fk", + "tableFrom": "security", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "security_username_applicationId_unique": { + "name": "security_username_applicationId_unique", + "nullsNotDistinct": false, + "columns": [ + "username", + "applicationId" + ] + } + } + }, + "public.port": { + "name": "port", + "schema": "", + "columns": { + "portId": { + "name": "portId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "publishedPort": { + "name": "publishedPort", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "targetPort": { + "name": "targetPort", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "protocol": { + "name": "protocol", + "type": "protocolType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "port_applicationId_application_applicationId_fk": { + "name": "port_applicationId_application_applicationId_fk", + "tableFrom": "port", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.redis": { + "name": "redis", + "schema": "", + "columns": { + "redisId": { + "name": "redisId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "redis_projectId_project_projectId_fk": { + "name": "redis_projectId_project_projectId_fk", + "tableFrom": "redis", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "redis_appName_unique": { + "name": "redis_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.compose": { + "name": "compose", + "schema": "", + "columns": { + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeFile": { + "name": "composeFile", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "refreshToken": { + "name": "refreshToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sourceType": { + "name": "sourceType", + "type": "sourceTypeCompose", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'github'" + }, + "composeType": { + "name": "composeType", + "type": "composeType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'docker-compose'" + }, + "repository": { + "name": "repository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner": { + "name": "owner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "autoDeploy": { + "name": "autoDeploy", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "gitlabProjectId": { + "name": "gitlabProjectId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "gitlabRepository": { + "name": "gitlabRepository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabOwner": { + "name": "gitlabOwner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabBranch": { + "name": "gitlabBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabPathNamespace": { + "name": "gitlabPathNamespace", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketRepository": { + "name": "bitbucketRepository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketOwner": { + "name": "bitbucketOwner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketBranch": { + "name": "bitbucketBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitUrl": { + "name": "customGitUrl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitBranch": { + "name": "customGitBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitSSHKeyId": { + "name": "customGitSSHKeyId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "composePath": { + "name": "composePath", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'./docker-compose.yml'" + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "randomize": { + "name": "randomize", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "composeStatus": { + "name": "composeStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "githubId": { + "name": "githubId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabId": { + "name": "gitlabId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketId": { + "name": "bitbucketId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "compose_customGitSSHKeyId_ssh-key_sshKeyId_fk": { + "name": "compose_customGitSSHKeyId_ssh-key_sshKeyId_fk", + "tableFrom": "compose", + "tableTo": "ssh-key", + "columnsFrom": [ + "customGitSSHKeyId" + ], + "columnsTo": [ + "sshKeyId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "compose_projectId_project_projectId_fk": { + "name": "compose_projectId_project_projectId_fk", + "tableFrom": "compose", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "compose_githubId_github_githubId_fk": { + "name": "compose_githubId_github_githubId_fk", + "tableFrom": "compose", + "tableTo": "github", + "columnsFrom": [ + "githubId" + ], + "columnsTo": [ + "githubId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "compose_gitlabId_gitlab_gitlabId_fk": { + "name": "compose_gitlabId_gitlab_gitlabId_fk", + "tableFrom": "compose", + "tableTo": "gitlab", + "columnsFrom": [ + "gitlabId" + ], + "columnsTo": [ + "gitlabId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "compose_bitbucketId_bitbucket_bitbucketId_fk": { + "name": "compose_bitbucketId_bitbucket_bitbucketId_fk", + "tableFrom": "compose", + "tableTo": "bitbucket", + "columnsFrom": [ + "bitbucketId" + ], + "columnsTo": [ + "bitbucketId" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.registry": { + "name": "registry", + "schema": "", + "columns": { + "registryId": { + "name": "registryId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "registryName": { + "name": "registryName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "imagePrefix": { + "name": "imagePrefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "registryUrl": { + "name": "registryUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "selfHosted": { + "name": "selfHosted", + "type": "RegistryType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'cloud'" + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "registry_adminId_admin_adminId_fk": { + "name": "registry_adminId_admin_adminId_fk", + "tableFrom": "registry", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.discord": { + "name": "discord", + "schema": "", + "columns": { + "discordId": { + "name": "discordId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "webhookUrl": { + "name": "webhookUrl", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.email": { + "name": "email", + "schema": "", + "columns": { + "emailId": { + "name": "emailId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "smtpServer": { + "name": "smtpServer", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "smtpPort": { + "name": "smtpPort", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "fromAddress": { + "name": "fromAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "toAddress": { + "name": "toAddress", + "type": "text[]", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.notification": { + "name": "notification", + "schema": "", + "columns": { + "notificationId": { + "name": "notificationId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appDeploy": { + "name": "appDeploy", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "appBuildError": { + "name": "appBuildError", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "databaseBackup": { + "name": "databaseBackup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "dokployRestart": { + "name": "dokployRestart", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "dockerCleanup": { + "name": "dockerCleanup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "notificationType": { + "name": "notificationType", + "type": "notificationType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slackId": { + "name": "slackId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "telegramId": { + "name": "telegramId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "discordId": { + "name": "discordId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "emailId": { + "name": "emailId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "notification_slackId_slack_slackId_fk": { + "name": "notification_slackId_slack_slackId_fk", + "tableFrom": "notification", + "tableTo": "slack", + "columnsFrom": [ + "slackId" + ], + "columnsTo": [ + "slackId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_telegramId_telegram_telegramId_fk": { + "name": "notification_telegramId_telegram_telegramId_fk", + "tableFrom": "notification", + "tableTo": "telegram", + "columnsFrom": [ + "telegramId" + ], + "columnsTo": [ + "telegramId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_discordId_discord_discordId_fk": { + "name": "notification_discordId_discord_discordId_fk", + "tableFrom": "notification", + "tableTo": "discord", + "columnsFrom": [ + "discordId" + ], + "columnsTo": [ + "discordId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_emailId_email_emailId_fk": { + "name": "notification_emailId_email_emailId_fk", + "tableFrom": "notification", + "tableTo": "email", + "columnsFrom": [ + "emailId" + ], + "columnsTo": [ + "emailId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.slack": { + "name": "slack", + "schema": "", + "columns": { + "slackId": { + "name": "slackId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "webhookUrl": { + "name": "webhookUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "channel": { + "name": "channel", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.telegram": { + "name": "telegram", + "schema": "", + "columns": { + "telegramId": { + "name": "telegramId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "botToken": { + "name": "botToken", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chatId": { + "name": "chatId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.ssh-key": { + "name": "ssh-key", + "schema": "", + "columns": { + "sshKeyId": { + "name": "sshKeyId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "publicKey": { + "name": "publicKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lastUsedAt": { + "name": "lastUsedAt", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.git_provider": { + "name": "git_provider", + "schema": "", + "columns": { + "gitProviderId": { + "name": "gitProviderId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerType": { + "name": "providerType", + "type": "gitProviderType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'github'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "authId": { + "name": "authId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "git_provider_authId_auth_id_fk": { + "name": "git_provider_authId_auth_id_fk", + "tableFrom": "git_provider", + "tableTo": "auth", + "columnsFrom": [ + "authId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.bitbucket": { + "name": "bitbucket", + "schema": "", + "columns": { + "bitbucketId": { + "name": "bitbucketId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "bitbucketUsername": { + "name": "bitbucketUsername", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "appPassword": { + "name": "appPassword", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketWorkspaceName": { + "name": "bitbucketWorkspaceName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitProviderId": { + "name": "gitProviderId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "bitbucket_gitProviderId_git_provider_gitProviderId_fk": { + "name": "bitbucket_gitProviderId_git_provider_gitProviderId_fk", + "tableFrom": "bitbucket", + "tableTo": "git_provider", + "columnsFrom": [ + "gitProviderId" + ], + "columnsTo": [ + "gitProviderId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.github": { + "name": "github", + "schema": "", + "columns": { + "githubId": { + "name": "githubId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "githubAppName": { + "name": "githubAppName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubAppId": { + "name": "githubAppId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "githubClientId": { + "name": "githubClientId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubClientSecret": { + "name": "githubClientSecret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubInstallationId": { + "name": "githubInstallationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubPrivateKey": { + "name": "githubPrivateKey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubWebhookSecret": { + "name": "githubWebhookSecret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitProviderId": { + "name": "gitProviderId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "github_gitProviderId_git_provider_gitProviderId_fk": { + "name": "github_gitProviderId_git_provider_gitProviderId_fk", + "tableFrom": "github", + "tableTo": "git_provider", + "columnsFrom": [ + "gitProviderId" + ], + "columnsTo": [ + "gitProviderId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.gitlab": { + "name": "gitlab", + "schema": "", + "columns": { + "gitlabId": { + "name": "gitlabId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "application_id": { + "name": "application_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "redirect_uri": { + "name": "redirect_uri", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "group_name": { + "name": "group_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "gitProviderId": { + "name": "gitProviderId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "gitlab_gitProviderId_git_provider_gitProviderId_fk": { + "name": "gitlab_gitProviderId_git_provider_gitProviderId_fk", + "tableFrom": "gitlab", + "tableTo": "git_provider", + "columnsFrom": [ + "gitProviderId" + ], + "columnsTo": [ + "gitProviderId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "public.buildType": { + "name": "buildType", + "schema": "public", + "values": [ + "dockerfile", + "heroku_buildpacks", + "paketo_buildpacks", + "nixpacks", + "static" + ] + }, + "public.sourceType": { + "name": "sourceType", + "schema": "public", + "values": [ + "docker", + "git", + "github", + "gitlab", + "bitbucket", + "drop" + ] + }, + "public.Roles": { + "name": "Roles", + "schema": "public", + "values": [ + "admin", + "user" + ] + }, + "public.domainType": { + "name": "domainType", + "schema": "public", + "values": [ + "compose", + "application" + ] + }, + "public.databaseType": { + "name": "databaseType", + "schema": "public", + "values": [ + "postgres", + "mariadb", + "mysql", + "mongo" + ] + }, + "public.deploymentStatus": { + "name": "deploymentStatus", + "schema": "public", + "values": [ + "running", + "done", + "error" + ] + }, + "public.mountType": { + "name": "mountType", + "schema": "public", + "values": [ + "bind", + "volume", + "file" + ] + }, + "public.serviceType": { + "name": "serviceType", + "schema": "public", + "values": [ + "application", + "postgres", + "mysql", + "mariadb", + "mongo", + "redis", + "compose" + ] + }, + "public.protocolType": { + "name": "protocolType", + "schema": "public", + "values": [ + "tcp", + "udp" + ] + }, + "public.applicationStatus": { + "name": "applicationStatus", + "schema": "public", + "values": [ + "idle", + "running", + "done", + "error" + ] + }, + "public.certificateType": { + "name": "certificateType", + "schema": "public", + "values": [ + "letsencrypt", + "none" + ] + }, + "public.composeType": { + "name": "composeType", + "schema": "public", + "values": [ + "docker-compose", + "stack" + ] + }, + "public.sourceTypeCompose": { + "name": "sourceTypeCompose", + "schema": "public", + "values": [ + "git", + "github", + "gitlab", + "bitbucket", + "raw" + ] + }, + "public.RegistryType": { + "name": "RegistryType", + "schema": "public", + "values": [ + "selfHosted", + "cloud" + ] + }, + "public.notificationType": { + "name": "notificationType", + "schema": "public", + "values": [ + "slack", + "telegram", + "discord", + "email" + ] + }, + "public.gitProviderType": { + "name": "gitProviderType", + "schema": "public", + "values": [ + "github", + "gitlab", + "bitbucket" + ] + } + }, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/dokploy/drizzle/meta/_journal.json b/apps/dokploy/drizzle/meta/_journal.json index d975604a..2bd9e2b3 100644 --- a/apps/dokploy/drizzle/meta/_journal.json +++ b/apps/dokploy/drizzle/meta/_journal.json @@ -246,6 +246,13 @@ "when": 1725256397019, "tag": "0034_aspiring_secret_warriors", "breakpoints": true + }, + { + "idx": 35, + "version": "6", + "when": 1725421774684, + "tag": "0035_tired_kinsey_walden", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/dokploy/server/api/routers/compose.ts b/apps/dokploy/server/api/routers/compose.ts index fff95bbd..62b13663 100644 --- a/apps/dokploy/server/api/routers/compose.ts +++ b/apps/dokploy/server/api/routers/compose.ts @@ -15,7 +15,10 @@ import { } from "@/server/queues/deployments-queue"; import { myQueue } from "@/server/queues/queueSetup"; import { createCommand } from "@/server/utils/builders/compose"; -import { randomizeComposeFile } from "@/server/utils/docker/compose"; +import { + randomizeComposeFile, + randomizeSpecificationFile, +} from "@/server/utils/docker/compose"; import { addDomainToCompose, cloneCompose } from "@/server/utils/docker/domain"; import { removeComposeDirectory } from "@/server/utils/filesystem/directory"; import { templates } from "@/templates/templates"; @@ -149,7 +152,12 @@ export const composeRouter = createTRPCRouter({ const compose = await findComposeById(input.composeId); const domains = await findDomainsByComposeId(input.composeId); - const composeFile = await addDomainToCompose(compose, domains); + let composeFile = await addDomainToCompose(compose, domains); + + if (compose.randomize && composeFile && compose.prefix) { + const result = randomizeSpecificationFile(composeFile, compose.prefix); + composeFile = result; + } return dump(composeFile, { lineWidth: 1000, }); diff --git a/apps/dokploy/server/db/schema/compose.ts b/apps/dokploy/server/db/schema/compose.ts index 91d43d94..c8de5289 100644 --- a/apps/dokploy/server/db/schema/compose.ts +++ b/apps/dokploy/server/db/schema/compose.ts @@ -64,6 +64,8 @@ export const compose = pgTable("compose", { command: text("command").notNull().default(""), // composePath: text("composePath").notNull().default("./docker-compose.yml"), + prefix: text("prefix").notNull().default(""), + randomize: boolean("randomize").notNull().default(false), composeStatus: applicationStatus("composeStatus").notNull().default("idle"), projectId: text("projectId") .notNull() diff --git a/apps/dokploy/server/utils/builders/compose.ts b/apps/dokploy/server/utils/builders/compose.ts index 9058aa5a..664f59ee 100644 --- a/apps/dokploy/server/utils/builders/compose.ts +++ b/apps/dokploy/server/utils/builders/compose.ts @@ -109,6 +109,10 @@ const createEnvFile = (compose: ComposeNested) => { envContent += "\nDOCKER_CONFIG=/root/.docker/config.json"; } + if (compose.randomize) { + envContent += `\nCOMPOSE_PREFIX=${compose.prefix}`; + } + const envFileContent = prepareEnvironmentVariables(envContent).join("\n"); if (!existsSync(dirname(envFilePath))) { diff --git a/apps/dokploy/server/utils/docker/compose.ts b/apps/dokploy/server/utils/docker/compose.ts index 410d9b24..229f8da5 100644 --- a/apps/dokploy/server/utils/docker/compose.ts +++ b/apps/dokploy/server/utils/docker/compose.ts @@ -27,6 +27,14 @@ export const randomizeComposeFile = async ( return dump(newComposeFile); }; +export const randomizeSpecificationFile = ( + composeSpec: ComposeSpecification, + prefix: string, +) => { + const newComposeFile = addPrefixToAllProperties(composeSpec, prefix); + return newComposeFile; +}; + export const addPrefixToAllProperties = ( composeData: ComposeSpecification, prefix: string, diff --git a/apps/dokploy/server/utils/docker/domain.ts b/apps/dokploy/server/utils/docker/domain.ts index 4f7e387a..1de7a49b 100644 --- a/apps/dokploy/server/utils/docker/domain.ts +++ b/apps/dokploy/server/utils/docker/domain.ts @@ -15,6 +15,7 @@ import type { DefinitionsService, PropertiesNetworks, } from "./types"; +import { randomizeSpecificationFile } from "./compose"; export const cloneCompose = async (compose: Compose) => { if (compose.sourceType === "github") { @@ -72,7 +73,12 @@ export const writeDomainsToCompose = async ( if (!domains.length) { return; } - const composeConverted = await addDomainToCompose(compose, domains); + let composeConverted = await addDomainToCompose(compose, domains); + + if (compose.randomize && composeConverted && compose.prefix) { + const result = randomizeSpecificationFile(composeConverted, compose.prefix); + composeConverted = result; + } const path = getComposePath(compose); const composeString = dump(composeConverted, { lineWidth: 1000 }); From 9c89208d83006cbbe2e34abd4deca46cf144982c Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:22:24 -0600 Subject: [PATCH 3/7] refactor: retrieve the correct names when adding a prefix --- apps/dokploy/server/api/routers/compose.ts | 6 +----- apps/dokploy/server/api/services/compose.ts | 12 +++++++++++- apps/dokploy/server/utils/docker/compose.ts | 5 ++++- apps/dokploy/server/utils/docker/domain.ts | 7 ++++++- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/apps/dokploy/server/api/routers/compose.ts b/apps/dokploy/server/api/routers/compose.ts index 62b13663..82dee89a 100644 --- a/apps/dokploy/server/api/routers/compose.ts +++ b/apps/dokploy/server/api/routers/compose.ts @@ -152,12 +152,8 @@ export const composeRouter = createTRPCRouter({ const compose = await findComposeById(input.composeId); const domains = await findDomainsByComposeId(input.composeId); - let composeFile = await addDomainToCompose(compose, domains); + const composeFile = await addDomainToCompose(compose, domains); - if (compose.randomize && composeFile && compose.prefix) { - const result = randomizeSpecificationFile(composeFile, compose.prefix); - composeFile = result; - } return dump(composeFile, { lineWidth: 1000, }); diff --git a/apps/dokploy/server/api/services/compose.ts b/apps/dokploy/server/api/services/compose.ts index ed783332..ca40e2c5 100644 --- a/apps/dokploy/server/api/services/compose.ts +++ b/apps/dokploy/server/api/services/compose.ts @@ -19,6 +19,7 @@ import { eq } from "drizzle-orm"; import { getDokployUrl } from "./admin"; import { createDeploymentCompose, updateDeploymentStatus } from "./deployment"; import { validUniqueServerAppName } from "./project"; +import { randomizeSpecificationFile } from "@/server/utils/docker/compose"; export type Compose = typeof compose.$inferSelect; @@ -117,7 +118,16 @@ export const loadServices = async ( await cloneCompose(compose); } - const composeData = await loadDockerCompose(compose); + let composeData = await loadDockerCompose(compose); + + if (compose.randomize && composeData) { + const randomizedCompose = randomizeSpecificationFile( + composeData, + compose.prefix, + ); + composeData = randomizedCompose; + } + if (!composeData?.services) { throw new TRPCError({ code: "NOT_FOUND", diff --git a/apps/dokploy/server/utils/docker/compose.ts b/apps/dokploy/server/utils/docker/compose.ts index 229f8da5..42a7c0f7 100644 --- a/apps/dokploy/server/utils/docker/compose.ts +++ b/apps/dokploy/server/utils/docker/compose.ts @@ -29,8 +29,11 @@ export const randomizeComposeFile = async ( export const randomizeSpecificationFile = ( composeSpec: ComposeSpecification, - prefix: string, + prefix?: string, ) => { + if (!prefix) { + return composeSpec; + } const newComposeFile = addPrefixToAllProperties(composeSpec, prefix); return newComposeFile; }; diff --git a/apps/dokploy/server/utils/docker/domain.ts b/apps/dokploy/server/utils/docker/domain.ts index 1de7a49b..5e08df51 100644 --- a/apps/dokploy/server/utils/docker/domain.ts +++ b/apps/dokploy/server/utils/docker/domain.ts @@ -94,12 +94,17 @@ export const addDomainToCompose = async ( domains: Domain[], ) => { const { appName } = compose; - const result = await loadDockerCompose(compose); + let result = await loadDockerCompose(compose); if (!result || domains.length === 0) { return null; } + if (compose.randomize) { + const randomized = randomizeSpecificationFile(result, compose.prefix); + result = randomized; + } + for (const domain of domains) { const { serviceName, https } = domain; if (!serviceName) { From beb84554e1e62d3ab0b61530cceb6c8da37d5f7f Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:32:34 -0600 Subject: [PATCH 4/7] refactor: remove unnecesary prefix validation --- apps/dokploy/server/utils/docker/domain.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/server/utils/docker/domain.ts b/apps/dokploy/server/utils/docker/domain.ts index 5e08df51..fa7046fd 100644 --- a/apps/dokploy/server/utils/docker/domain.ts +++ b/apps/dokploy/server/utils/docker/domain.ts @@ -75,7 +75,7 @@ export const writeDomainsToCompose = async ( } let composeConverted = await addDomainToCompose(compose, domains); - if (compose.randomize && composeConverted && compose.prefix) { + if (compose.randomize && composeConverted) { const result = randomizeSpecificationFile(composeConverted, compose.prefix); composeConverted = result; } From b6fd92aaddcc71574d937c8b4f760f74f90755e2 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:58:56 -0600 Subject: [PATCH 5/7] refactor: change prefix to suffix --- apps/dokploy/__test__/compose/compose.test.ts | 26 ++++---- .../compose/config/config-root.test.ts | 40 ++++++------ .../compose/config/config-service.test.ts | 34 +++++----- .../__test__/compose/config/config.test.ts | 22 +++---- .../compose/network/network-root.test.ts | 56 ++++++++-------- .../compose/network/network-service.test.ts | 62 +++++++++--------- .../__test__/compose/network/network.test.ts | 56 ++++++++-------- .../compose/secrets/secret-root.test.ts | 26 ++++---- .../compose/secrets/secret-services.test.ts | 34 +++++----- .../__test__/compose/secrets/secret.test.ts | 20 +++--- .../service/service-container-name.test.ts | 20 +++--- .../service/service-depends-on.test.ts | 64 +++++++++---------- .../compose/service/service-extends.test.ts | 46 ++++++------- .../compose/service/service-links.test.ts | 28 ++++---- .../compose/service/service-names.test.ts | 14 ++-- .../__test__/compose/service/service.test.ts | 30 ++++----- .../service/sevice-volumes-from.test.ts | 28 ++++---- .../__test__/compose/volume/volume-2.test.ts | 42 ++++++------ .../compose/volume/volume-root.test.ts | 32 +++++----- .../compose/volume/volume-services.test.ts | 22 +++---- .../__test__/compose/volume/volume.test.ts | 28 ++++---- apps/dokploy/__test__/traefik/traefik.test.ts | 4 +- .../compose/general/randomize-compose.tsx | 26 ++++---- ...insey_walden.sql => 0035_cool_gravity.sql} | 2 +- apps/dokploy/drizzle/meta/0035_snapshot.json | 6 +- apps/dokploy/drizzle/meta/_journal.json | 4 +- apps/dokploy/server/api/routers/compose.ts | 2 +- apps/dokploy/server/api/services/compose.ts | 4 +- apps/dokploy/server/db/schema/compose.ts | 4 +- apps/dokploy/server/utils/builders/compose.ts | 2 +- apps/dokploy/server/utils/docker/compose.ts | 36 +++++------ .../server/utils/docker/compose/configs.ts | 26 ++++---- .../server/utils/docker/compose/network.ts | 28 ++++---- .../server/utils/docker/compose/secrets.ts | 26 ++++---- .../server/utils/docker/compose/service.ts | 28 ++++---- .../server/utils/docker/compose/volume.ts | 26 ++++---- apps/dokploy/server/utils/docker/domain.ts | 6 +- 37 files changed, 480 insertions(+), 480 deletions(-) rename apps/dokploy/drizzle/{0035_tired_kinsey_walden.sql => 0035_cool_gravity.sql} (61%) diff --git a/apps/dokploy/__test__/compose/compose.test.ts b/apps/dokploy/__test__/compose/compose.test.ts index 1e728b99..4c47b111 100644 --- a/apps/dokploy/__test__/compose/compose.test.ts +++ b/apps/dokploy/__test__/compose/compose.test.ts @@ -1,4 +1,4 @@ -import { addPrefixToAllProperties } from "@/server/utils/docker/compose"; +import { addSuffixToAllProperties } from "@/server/utils/docker/compose"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -119,11 +119,11 @@ secrets: file: ./db_password.txt `) as ComposeSpecification; -test("Add prefix to all properties in compose file 1", () => { +test("Add suffix to all properties in compose file 1", () => { const composeData = load(composeFile1) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllProperties(composeData, prefix); + const updatedComposeData = addSuffixToAllProperties(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFile1); }); @@ -242,11 +242,11 @@ secrets: file: ./db_password.txt `) as ComposeSpecification; -test("Add prefix to all properties in compose file 2", () => { +test("Add suffix to all properties in compose file 2", () => { const composeData = load(composeFile2) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllProperties(composeData, prefix); + const updatedComposeData = addSuffixToAllProperties(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFile2); }); @@ -365,11 +365,11 @@ secrets: file: ./service_secret.txt `) as ComposeSpecification; -test("Add prefix to all properties in compose file 3", () => { +test("Add suffix to all properties in compose file 3", () => { const composeData = load(composeFile3) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllProperties(composeData, prefix); + const updatedComposeData = addSuffixToAllProperties(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFile3); }); @@ -466,11 +466,11 @@ volumes: driver: local `) as ComposeSpecification; -test("Add prefix to all properties in Plausible compose file", () => { +test("Add suffix to all properties in Plausible compose file", () => { const composeData = load(composeFile) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllProperties(composeData, prefix); + const updatedComposeData = addSuffixToAllProperties(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFile); }); diff --git a/apps/dokploy/__test__/compose/config/config-root.test.ts b/apps/dokploy/__test__/compose/config/config-root.test.ts index 88e8b357..7f4311f6 100644 --- a/apps/dokploy/__test__/compose/config/config-root.test.ts +++ b/apps/dokploy/__test__/compose/config/config-root.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToConfigsRoot } from "@/server/utils/docker/compose/configs"; +import { addSuffixToConfigsRoot } from "@/server/utils/docker/compose/configs"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -23,19 +23,19 @@ configs: file: ./web-config.yml `; -test("Add prefix to configs in root property", () => { +test("Add suffix to configs in root property", () => { const composeData = load(composeFile) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.configs) { return; } - const configs = addPrefixToConfigsRoot(composeData.configs, prefix); + const configs = addSuffixToConfigsRoot(composeData.configs, suffix); expect(configs).toBeDefined(); for (const configKey of Object.keys(configs)) { - expect(configKey).toContain(`-${prefix}`); + expect(configKey).toContain(`-${suffix}`); expect(configs[configKey]).toBeDefined(); } }); @@ -59,23 +59,23 @@ configs: file: ./another-config.yml `; -test("Add prefix to multiple configs in root property", () => { +test("Add suffix to multiple configs in root property", () => { const composeData = load(composeFileMultipleConfigs) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.configs) { return; } - const configs = addPrefixToConfigsRoot(composeData.configs, prefix); + const configs = addSuffixToConfigsRoot(composeData.configs, suffix); expect(configs).toBeDefined(); for (const configKey of Object.keys(configs)) { - expect(configKey).toContain(`-${prefix}`); + expect(configKey).toContain(`-${suffix}`); expect(configs[configKey]).toBeDefined(); } - expect(configs).toHaveProperty(`web-config-${prefix}`); - expect(configs).toHaveProperty(`another-config-${prefix}`); + expect(configs).toHaveProperty(`web-config-${suffix}`); + expect(configs).toHaveProperty(`another-config-${suffix}`); }); const composeFileDifferentProperties = ` @@ -92,25 +92,25 @@ configs: external: true `; -test("Add prefix to configs with different properties in root property", () => { +test("Add suffix to configs with different properties in root property", () => { const composeData = load( composeFileDifferentProperties, ) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.configs) { return; } - const configs = addPrefixToConfigsRoot(composeData.configs, prefix); + const configs = addSuffixToConfigsRoot(composeData.configs, suffix); expect(configs).toBeDefined(); for (const configKey of Object.keys(configs)) { - expect(configKey).toContain(`-${prefix}`); + expect(configKey).toContain(`-${suffix}`); expect(configs[configKey]).toBeDefined(); } - expect(configs).toHaveProperty(`web-config-${prefix}`); - expect(configs).toHaveProperty(`special-config-${prefix}`); + expect(configs).toHaveProperty(`web-config-${suffix}`); + expect(configs).toHaveProperty(`special-config-${suffix}`); }); const composeFileConfigRoot = ` @@ -162,15 +162,15 @@ configs: file: ./db-config.yml `) as ComposeSpecification; -test("Add prefix to configs in root property", () => { +test("Add suffix to configs in root property", () => { const composeData = load(composeFileConfigRoot) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; if (!composeData?.configs) { return; } - const configs = addPrefixToConfigsRoot(composeData.configs, prefix); + const configs = addSuffixToConfigsRoot(composeData.configs, suffix); const updatedComposeData = { ...composeData, configs }; // Verificar que el resultado coincide con el archivo esperado diff --git a/apps/dokploy/__test__/compose/config/config-service.test.ts b/apps/dokploy/__test__/compose/config/config-service.test.ts index df2bb417..4d3051a5 100644 --- a/apps/dokploy/__test__/compose/config/config-service.test.ts +++ b/apps/dokploy/__test__/compose/config/config-service.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToConfigsInServices } from "@/server/utils/docker/compose/configs"; +import { addSuffixToConfigsInServices } from "@/server/utils/docker/compose/configs"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -19,19 +19,19 @@ configs: file: ./web-config.yml `; -test("Add prefix to configs in services", () => { +test("Add suffix to configs in services", () => { const composeData = load(composeFile) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.services) { return; } - const services = addPrefixToConfigsInServices(composeData.services, prefix); + const services = addSuffixToConfigsInServices(composeData.services, suffix); const actualComposeData = { ...composeData, services }; expect(actualComposeData.services?.web?.configs).toContainEqual({ - source: `web-config-${prefix}`, + source: `web-config-${suffix}`, target: "/etc/nginx/nginx.conf", }); }); @@ -51,17 +51,17 @@ configs: file: ./web-config.yml `; -test("Add prefix to configs in services with single config", () => { +test("Add suffix to configs in services with single config", () => { const composeData = load( composeFileSingleServiceConfig, ) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.services) { return; } - const services = addPrefixToConfigsInServices(composeData.services, prefix); + const services = addSuffixToConfigsInServices(composeData.services, suffix); expect(services).toBeDefined(); for (const serviceKey of Object.keys(services)) { @@ -69,7 +69,7 @@ test("Add prefix to configs in services with single config", () => { if (serviceConfigs) { for (const config of serviceConfigs) { if (typeof config === "object") { - expect(config.source).toContain(`-${prefix}`); + expect(config.source).toContain(`-${suffix}`); } } } @@ -105,17 +105,17 @@ configs: file: ./common-config.yml `; -test("Add prefix to configs in services with multiple configs", () => { +test("Add suffix to configs in services with multiple configs", () => { const composeData = load( composeFileMultipleServicesConfigs, ) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.services) { return; } - const services = addPrefixToConfigsInServices(composeData.services, prefix); + const services = addSuffixToConfigsInServices(composeData.services, suffix); expect(services).toBeDefined(); for (const serviceKey of Object.keys(services)) { @@ -123,7 +123,7 @@ test("Add prefix to configs in services with multiple configs", () => { if (serviceConfigs) { for (const config of serviceConfigs) { if (typeof config === "object") { - expect(config.source).toContain(`-${prefix}`); + expect(config.source).toContain(`-${suffix}`); } } } @@ -179,17 +179,17 @@ services: `) as ComposeSpecification; -test("Add prefix to configs in services", () => { +test("Add suffix to configs in services", () => { const composeData = load(composeFileConfigServices) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; if (!composeData?.services) { return; } - const updatedComposeData = addPrefixToConfigsInServices( + const updatedComposeData = addSuffixToConfigsInServices( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; diff --git a/apps/dokploy/__test__/compose/config/config.test.ts b/apps/dokploy/__test__/compose/config/config.test.ts index 8f17ac86..4677fbe9 100644 --- a/apps/dokploy/__test__/compose/config/config.test.ts +++ b/apps/dokploy/__test__/compose/config/config.test.ts @@ -1,7 +1,7 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; import { - addPrefixToAllConfigs, - addPrefixToConfigsRoot, + addSuffixToAllConfigs, + addSuffixToConfigsRoot, } from "@/server/utils/docker/compose/configs"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; @@ -80,12 +80,12 @@ configs: file: ./db-config.yml `) as ComposeSpecification; -test("Add prefix to all configs in root and services", () => { +test("Add suffix to all configs in root and services", () => { const composeData = load(composeFileCombinedConfigs) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllConfigs(composeData, prefix); + const updatedComposeData = addSuffixToAllConfigs(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFileCombinedConfigs); }); @@ -162,14 +162,14 @@ configs: file: ./db-config.yml `) as ComposeSpecification; -test("Add prefix to configs with environment and external", () => { +test("Add suffix to configs with environment and external", () => { const composeData = load( composeFileWithEnvAndExternal, ) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllConfigs(composeData, prefix); + const updatedComposeData = addSuffixToAllConfigs(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFileWithEnvAndExternal); }); @@ -234,14 +234,14 @@ configs: file: ./db-config.yml `) as ComposeSpecification; -test("Add prefix to configs with template driver and labels", () => { +test("Add suffix to configs with template driver and labels", () => { const composeData = load( composeFileWithTemplateDriverAndLabels, ) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllConfigs(composeData, prefix); + const updatedComposeData = addSuffixToAllConfigs(composeData, suffix); expect(updatedComposeData).toEqual( expectedComposeFileWithTemplateDriverAndLabels, diff --git a/apps/dokploy/__test__/compose/network/network-root.test.ts b/apps/dokploy/__test__/compose/network/network-root.test.ts index 297f358f..b5156b17 100644 --- a/apps/dokploy/__test__/compose/network/network-root.test.ts +++ b/apps/dokploy/__test__/compose/network/network-root.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToNetworksRoot } from "@/server/utils/docker/compose/network"; +import { addSuffixToNetworksRoot } from "@/server/utils/docker/compose/network"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -35,19 +35,19 @@ test("Generate random hash with 8 characters", () => { expect(hash.length).toBe(8); }); -test("Add prefix to networks root property", () => { +test("Add suffix to networks root property", () => { const composeData = load(composeFile) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.networks) { return; } - const networks = addPrefixToNetworksRoot(composeData.networks, prefix); + const networks = addSuffixToNetworksRoot(composeData.networks, suffix); expect(networks).toBeDefined(); for (const volumeKey of Object.keys(networks)) { - expect(volumeKey).toContain(`-${prefix}`); + expect(volumeKey).toContain(`-${suffix}`); } }); @@ -79,19 +79,19 @@ networks: internal: true `; -test("Add prefix to advanced networks root property (2 TRY)", () => { +test("Add suffix to advanced networks root property (2 TRY)", () => { const composeData = load(composeFile2) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.networks) { return; } - const networks = addPrefixToNetworksRoot(composeData.networks, prefix); + const networks = addSuffixToNetworksRoot(composeData.networks, suffix); expect(networks).toBeDefined(); for (const networkKey of Object.keys(networks)) { - expect(networkKey).toContain(`-${prefix}`); + expect(networkKey).toContain(`-${suffix}`); } }); @@ -120,19 +120,19 @@ networks: external: true `; -test("Add prefix to networks with external properties", () => { +test("Add suffix to networks with external properties", () => { const composeData = load(composeFile3) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.networks) { return; } - const networks = addPrefixToNetworksRoot(composeData.networks, prefix); + const networks = addSuffixToNetworksRoot(composeData.networks, suffix); expect(networks).toBeDefined(); for (const networkKey of Object.keys(networks)) { - expect(networkKey).toContain(`-${prefix}`); + expect(networkKey).toContain(`-${suffix}`); } }); @@ -160,19 +160,19 @@ networks: external: true `; -test("Add prefix to networks with IPAM configurations", () => { +test("Add suffix to networks with IPAM configurations", () => { const composeData = load(composeFile4) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.networks) { return; } - const networks = addPrefixToNetworksRoot(composeData.networks, prefix); + const networks = addSuffixToNetworksRoot(composeData.networks, suffix); expect(networks).toBeDefined(); for (const networkKey of Object.keys(networks)) { - expect(networkKey).toContain(`-${prefix}`); + expect(networkKey).toContain(`-${suffix}`); } }); @@ -201,19 +201,19 @@ networks: external: true `; -test("Add prefix to networks with custom options", () => { +test("Add suffix to networks with custom options", () => { const composeData = load(composeFile5) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.networks) { return; } - const networks = addPrefixToNetworksRoot(composeData.networks, prefix); + const networks = addSuffixToNetworksRoot(composeData.networks, suffix); expect(networks).toBeDefined(); for (const networkKey of Object.keys(networks)) { - expect(networkKey).toContain(`-${prefix}`); + expect(networkKey).toContain(`-${suffix}`); } }); @@ -240,7 +240,7 @@ networks: external: true `; -// Expected compose file with static prefix `testhash` +// Expected compose file with static suffix `testhash` const expectedComposeFile6 = ` version: "3.8" @@ -264,15 +264,15 @@ networks: external: true `; -test("Add prefix to networks with static prefix", () => { +test("Add suffix to networks with static suffix", () => { const composeData = load(composeFile6) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; if (!composeData?.networks) { return; } - const networks = addPrefixToNetworksRoot(composeData.networks, prefix); + const networks = addSuffixToNetworksRoot(composeData.networks, suffix); const expectedComposeData = load( expectedComposeFile6, @@ -316,15 +316,15 @@ networks: external: true name: dokploy-network `; -test("It shoudn't add prefix to dokploy-network", () => { +test("It shoudn't add suffix to dokploy-network", () => { const composeData = load(composeFile7) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.networks) { return; } - const networks = addPrefixToNetworksRoot(composeData.networks, prefix); + const networks = addSuffixToNetworksRoot(composeData.networks, suffix); expect(networks).toBeDefined(); for (const networkKey of Object.keys(networks)) { diff --git a/apps/dokploy/__test__/compose/network/network-service.test.ts b/apps/dokploy/__test__/compose/network/network-service.test.ts index 6f96c11d..92890e17 100644 --- a/apps/dokploy/__test__/compose/network/network-service.test.ts +++ b/apps/dokploy/__test__/compose/network/network-service.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToServiceNetworks } from "@/server/utils/docker/compose/network"; +import { addSuffixToServiceNetworks } from "@/server/utils/docker/compose/network"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -20,30 +20,30 @@ services: - backend `; -test("Add prefix to networks in services", () => { +test("Add suffix to networks in services", () => { const composeData = load(composeFile) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.services) { return; } - const services = addPrefixToServiceNetworks(composeData.services, prefix); + const services = addSuffixToServiceNetworks(composeData.services, suffix); const actualComposeData = { ...composeData, services }; expect(actualComposeData?.services?.web?.networks).toContain( - `frontend-${prefix}`, + `frontend-${suffix}`, ); expect(actualComposeData?.services?.api?.networks).toContain( - `backend-${prefix}`, + `backend-${suffix}`, ); const apiNetworks = actualComposeData?.services?.api?.networks; expect(apiNetworks).toBeDefined(); expect(actualComposeData?.services?.api?.networks).toContain( - `backend-${prefix}`, + `backend-${suffix}`, ); }); @@ -64,26 +64,26 @@ networks: driver: bridge `; -test("Add prefix to networks in services with aliases", () => { +test("Add suffix to networks in services with aliases", () => { const composeData = load(composeFile2) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.services) { return; } - const services = addPrefixToServiceNetworks(composeData.services, prefix); + const services = addSuffixToServiceNetworks(composeData.services, suffix); const actualComposeData = { ...composeData, services }; expect(actualComposeData.services?.api?.networks).toHaveProperty( - `frontend-${prefix}`, + `frontend-${suffix}`, ); const networkConfig = actualComposeData?.services?.api?.networks as { [key: string]: { aliases?: string[] }; }; - expect(networkConfig[`frontend-${prefix}`]).toBeDefined(); - expect(networkConfig[`frontend-${prefix}`]?.aliases).toContain("api"); + expect(networkConfig[`frontend-${suffix}`]).toBeDefined(); + expect(networkConfig[`frontend-${suffix}`]?.aliases).toContain("api"); expect(actualComposeData.services?.api?.networks).not.toHaveProperty( "frontend-ash", @@ -104,19 +104,19 @@ networks: driver: bridge `; -test("Add prefix to networks in services (Object with simple networks)", () => { +test("Add suffix to networks in services (Object with simple networks)", () => { const composeData = load(composeFile3) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.services) { return; } - const services = addPrefixToServiceNetworks(composeData.services, prefix); + const services = addSuffixToServiceNetworks(composeData.services, suffix); const actualComposeData = { ...composeData, services }; expect(actualComposeData.services?.redis?.networks).toHaveProperty( - `backend-${prefix}`, + `backend-${suffix}`, ); }); @@ -150,36 +150,36 @@ networks: driver: bridge `; -test("Add prefix to networks in services (combined case)", () => { +test("Add suffix to networks in services (combined case)", () => { const composeData = load(composeFileCombined) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.services) { return; } - const services = addPrefixToServiceNetworks(composeData.services, prefix); + const services = addSuffixToServiceNetworks(composeData.services, suffix); const actualComposeData = { ...composeData, services }; // Caso 1: ListOfStrings expect(actualComposeData.services?.web?.networks).toContain( - `frontend-${prefix}`, + `frontend-${suffix}`, ); expect(actualComposeData.services?.web?.networks).toContain( - `backend-${prefix}`, + `backend-${suffix}`, ); // Caso 2: Objeto con aliases const apiNetworks = actualComposeData.services?.api?.networks as { [key: string]: unknown; }; - expect(apiNetworks).toHaveProperty(`frontend-${prefix}`); - expect(apiNetworks[`frontend-${prefix}`]).toBeDefined(); + expect(apiNetworks).toHaveProperty(`frontend-${suffix}`); + expect(apiNetworks[`frontend-${suffix}`]).toBeDefined(); expect(apiNetworks).not.toHaveProperty("frontend"); // Caso 3: Objeto con redes simples const redisNetworks = actualComposeData.services?.redis?.networks; - expect(redisNetworks).toHaveProperty(`backend-${prefix}`); + expect(redisNetworks).toHaveProperty(`backend-${suffix}`); expect(redisNetworks).not.toHaveProperty("backend"); }); @@ -193,15 +193,15 @@ services: - dokploy-network `; -test("It shoudn't add prefix to dokploy-network in services", () => { +test("It shoudn't add suffix to dokploy-network in services", () => { const composeData = load(composeFile7) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.services) { return; } - const networks = addPrefixToServiceNetworks(composeData.services, prefix); + const networks = addSuffixToServiceNetworks(composeData.services, suffix); const service = networks.web; expect(service).toBeDefined(); @@ -242,15 +242,15 @@ services: `; -test("It shoudn't add prefix to dokploy-network in services multiples cases", () => { +test("It shoudn't add suffix to dokploy-network in services multiples cases", () => { const composeData = load(composeFile8) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.services) { return; } - const networks = addPrefixToServiceNetworks(composeData.services, prefix); + const networks = addSuffixToServiceNetworks(composeData.services, suffix); const service = networks.web; const api = networks.api; const redis = networks.redis; diff --git a/apps/dokploy/__test__/compose/network/network.test.ts b/apps/dokploy/__test__/compose/network/network.test.ts index 354fd650..c8a9e9f3 100644 --- a/apps/dokploy/__test__/compose/network/network.test.ts +++ b/apps/dokploy/__test__/compose/network/network.test.ts @@ -1,9 +1,9 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; import { - addPrefixToAllNetworks, - addPrefixToServiceNetworks, + addSuffixToAllNetworks, + addSuffixToServiceNetworks, } from "@/server/utils/docker/compose/network"; -import { addPrefixToNetworksRoot } from "@/server/utils/docker/compose/network"; +import { addSuffixToNetworksRoot } from "@/server/utils/docker/compose/network"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -38,54 +38,54 @@ networks: driver: bridge `; -test("Add prefix to networks in services and root (combined case)", () => { +test("Add suffix to networks in services and root (combined case)", () => { const composeData = load(composeFileCombined) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); // Prefijo para redes definidas en el root if (composeData.networks) { - composeData.networks = addPrefixToNetworksRoot( + composeData.networks = addSuffixToNetworksRoot( composeData.networks, - prefix, + suffix, ); } // Prefijo para redes definidas en los servicios if (composeData.services) { - composeData.services = addPrefixToServiceNetworks( + composeData.services = addSuffixToServiceNetworks( composeData.services, - prefix, + suffix, ); } const actualComposeData = { ...composeData }; // Verificar redes en root - expect(actualComposeData.networks).toHaveProperty(`frontend-${prefix}`); - expect(actualComposeData.networks).toHaveProperty(`backend-${prefix}`); + expect(actualComposeData.networks).toHaveProperty(`frontend-${suffix}`); + expect(actualComposeData.networks).toHaveProperty(`backend-${suffix}`); expect(actualComposeData.networks).not.toHaveProperty("frontend"); expect(actualComposeData.networks).not.toHaveProperty("backend"); // Caso 1: ListOfStrings expect(actualComposeData.services?.web?.networks).toContain( - `frontend-${prefix}`, + `frontend-${suffix}`, ); expect(actualComposeData.services?.web?.networks).toContain( - `backend-${prefix}`, + `backend-${suffix}`, ); // Caso 2: Objeto con aliases const apiNetworks = actualComposeData.services?.api?.networks as { [key: string]: { aliases?: string[] }; }; - expect(apiNetworks).toHaveProperty(`frontend-${prefix}`); - expect(apiNetworks?.[`frontend-${prefix}`]?.aliases).toContain("api"); + expect(apiNetworks).toHaveProperty(`frontend-${suffix}`); + expect(apiNetworks?.[`frontend-${suffix}`]?.aliases).toContain("api"); expect(apiNetworks).not.toHaveProperty("frontend"); // Caso 3: Objeto con redes simples const redisNetworks = actualComposeData.services?.redis?.networks; - expect(redisNetworks).toHaveProperty(`backend-${prefix}`); + expect(redisNetworks).toHaveProperty(`backend-${suffix}`); expect(redisNetworks).not.toHaveProperty("backend"); }); @@ -119,14 +119,14 @@ networks: driver: bridge `); -test("Add prefix to networks in compose file", () => { +test("Add suffix to networks in compose file", () => { const composeData = load(composeFileCombined) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; if (!composeData?.networks) { return; } - const updatedComposeData = addPrefixToAllNetworks(composeData, prefix); + const updatedComposeData = addSuffixToAllNetworks(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFile); }); @@ -181,11 +181,11 @@ networks: driver: bridge `); -test("Add prefix to networks in compose file with external and internal networks", () => { +test("Add suffix to networks in compose file with external and internal networks", () => { const composeData = load(composeFile2) as ComposeSpecification; - const prefix = "testhash"; - const updatedComposeData = addPrefixToAllNetworks(composeData, prefix); + const suffix = "testhash"; + const updatedComposeData = addSuffixToAllNetworks(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFile2); }); @@ -246,11 +246,11 @@ networks: com.docker.network.bridge.enable_icc: "true" `); -test("Add prefix to networks in compose file with multiple services and complex network configurations", () => { +test("Add suffix to networks in compose file with multiple services and complex network configurations", () => { const composeData = load(composeFile3) as ComposeSpecification; - const prefix = "testhash"; - const updatedComposeData = addPrefixToAllNetworks(composeData, prefix); + const suffix = "testhash"; + const updatedComposeData = addSuffixToAllNetworks(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFile3); }); @@ -325,11 +325,11 @@ networks: `); -test("Expect don't add prefix to dokploy-network in compose file with multiple services and complex network configurations", () => { +test("Expect don't add suffix to dokploy-network in compose file with multiple services and complex network configurations", () => { const composeData = load(composeFile4) as ComposeSpecification; - const prefix = "testhash"; - const updatedComposeData = addPrefixToAllNetworks(composeData, prefix); + const suffix = "testhash"; + const updatedComposeData = addSuffixToAllNetworks(composeData, suffix); console.log(updatedComposeData); expect(updatedComposeData).toEqual(expectedComposeFile4); }); diff --git a/apps/dokploy/__test__/compose/secrets/secret-root.test.ts b/apps/dokploy/__test__/compose/secrets/secret-root.test.ts index 61f9f818..3185b966 100644 --- a/apps/dokploy/__test__/compose/secrets/secret-root.test.ts +++ b/apps/dokploy/__test__/compose/secrets/secret-root.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToSecretsRoot } from "@/server/utils/docker/compose/secrets"; +import { addSuffixToSecretsRoot } from "@/server/utils/docker/compose/secrets"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { dump, load } from "js-yaml"; import { expect, test } from "vitest"; @@ -23,18 +23,18 @@ secrets: file: ./db_password.txt `; -test("Add prefix to secrets in root property", () => { +test("Add suffix to secrets in root property", () => { const composeData = load(composeFileSecretsRoot) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.secrets) { return; } - const secrets = addPrefixToSecretsRoot(composeData.secrets, prefix); + const secrets = addSuffixToSecretsRoot(composeData.secrets, suffix); expect(secrets).toBeDefined(); if (secrets) { for (const secretKey of Object.keys(secrets)) { - expect(secretKey).toContain(`-${prefix}`); + expect(secretKey).toContain(`-${suffix}`); expect(secrets[secretKey]).toBeDefined(); } } @@ -52,19 +52,19 @@ secrets: file: ./api_key.txt `; -test("Add prefix to secrets in root property (Test 1)", () => { +test("Add suffix to secrets in root property (Test 1)", () => { const composeData = load(composeFileSecretsRoot1) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.secrets) { return; } - const secrets = addPrefixToSecretsRoot(composeData.secrets, prefix); + const secrets = addSuffixToSecretsRoot(composeData.secrets, suffix); expect(secrets).toBeDefined(); if (secrets) { for (const secretKey of Object.keys(secrets)) { - expect(secretKey).toContain(`-${prefix}`); + expect(secretKey).toContain(`-${suffix}`); expect(secrets[secretKey]).toBeDefined(); } } @@ -84,19 +84,19 @@ secrets: external: true `; -test("Add prefix to secrets in root property (Test 2)", () => { +test("Add suffix to secrets in root property (Test 2)", () => { const composeData = load(composeFileSecretsRoot2) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.secrets) { return; } - const secrets = addPrefixToSecretsRoot(composeData.secrets, prefix); + const secrets = addSuffixToSecretsRoot(composeData.secrets, suffix); expect(secrets).toBeDefined(); if (secrets) { for (const secretKey of Object.keys(secrets)) { - expect(secretKey).toContain(`-${prefix}`); + expect(secretKey).toContain(`-${suffix}`); expect(secrets[secretKey]).toBeDefined(); } } diff --git a/apps/dokploy/__test__/compose/secrets/secret-services.test.ts b/apps/dokploy/__test__/compose/secrets/secret-services.test.ts index 1a58314d..4a3df137 100644 --- a/apps/dokploy/__test__/compose/secrets/secret-services.test.ts +++ b/apps/dokploy/__test__/compose/secrets/secret-services.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToSecretsInServices } from "@/server/utils/docker/compose/secrets"; +import { addSuffixToSecretsInServices } from "@/server/utils/docker/compose/secrets"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -18,22 +18,22 @@ secrets: file: ./db_password.txt `; -test("Add prefix to secrets in services", () => { +test("Add suffix to secrets in services", () => { const composeData = load(composeFileSecretsServices) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToSecretsInServices( + const updatedComposeData = addSuffixToSecretsInServices( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; expect(actualComposeData.services?.db?.secrets).toContain( - `db_password-${prefix}`, + `db_password-${suffix}`, ); }); @@ -51,22 +51,22 @@ secrets: file: ./app_secret.txt `; -test("Add prefix to secrets in services (Test 1)", () => { +test("Add suffix to secrets in services (Test 1)", () => { const composeData = load(composeFileSecretsServices1) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToSecretsInServices( + const updatedComposeData = addSuffixToSecretsInServices( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; expect(actualComposeData.services?.app?.secrets).toContain( - `app_secret-${prefix}`, + `app_secret-${suffix}`, ); }); @@ -90,24 +90,24 @@ secrets: file: ./frontend_secret.txt `; -test("Add prefix to secrets in services (Test 2)", () => { +test("Add suffix to secrets in services (Test 2)", () => { const composeData = load(composeFileSecretsServices2) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToSecretsInServices( + const updatedComposeData = addSuffixToSecretsInServices( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; expect(actualComposeData.services?.backend?.secrets).toContain( - `backend_secret-${prefix}`, + `backend_secret-${suffix}`, ); expect(actualComposeData.services?.frontend?.secrets).toContain( - `frontend_secret-${prefix}`, + `frontend_secret-${suffix}`, ); }); diff --git a/apps/dokploy/__test__/compose/secrets/secret.test.ts b/apps/dokploy/__test__/compose/secrets/secret.test.ts index 7922eb20..ea3552f3 100644 --- a/apps/dokploy/__test__/compose/secrets/secret.test.ts +++ b/apps/dokploy/__test__/compose/secrets/secret.test.ts @@ -1,4 +1,4 @@ -import { addPrefixToAllSecrets } from "@/server/utils/docker/compose/secrets"; +import { addSuffixToAllSecrets } from "@/server/utils/docker/compose/secrets"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -47,11 +47,11 @@ secrets: file: ./app_secret.txt `) as ComposeSpecification; -test("Add prefix to all secrets", () => { +test("Add suffix to all secrets", () => { const composeData = load(composeFileCombinedSecrets) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllSecrets(composeData, prefix); + const updatedComposeData = addSuffixToAllSecrets(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFileCombinedSecrets); }); @@ -98,11 +98,11 @@ secrets: file: ./cache_secret.txt `) as ComposeSpecification; -test("Add prefix to all secrets (3rd Case)", () => { +test("Add suffix to all secrets (3rd Case)", () => { const composeData = load(composeFileCombinedSecrets3) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllSecrets(composeData, prefix); + const updatedComposeData = addSuffixToAllSecrets(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFileCombinedSecrets3); }); @@ -149,11 +149,11 @@ secrets: file: ./db_password.txt `) as ComposeSpecification; -test("Add prefix to all secrets (4th Case)", () => { +test("Add suffix to all secrets (4th Case)", () => { const composeData = load(composeFileCombinedSecrets4) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllSecrets(composeData, prefix); + const updatedComposeData = addSuffixToAllSecrets(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFileCombinedSecrets4); }); diff --git a/apps/dokploy/__test__/compose/service/service-container-name.test.ts b/apps/dokploy/__test__/compose/service/service-container-name.test.ts index 9f5fe9ed..623b5381 100644 --- a/apps/dokploy/__test__/compose/service/service-container-name.test.ts +++ b/apps/dokploy/__test__/compose/service/service-container-name.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToServiceNames } from "@/server/utils/docker/compose/service"; +import { addSuffixToServiceNames } from "@/server/utils/docker/compose/service"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -27,33 +27,33 @@ test("Generate random hash with 8 characters", () => { expect(hash.length).toBe(8); }); -test("Add prefix to service names with container_name in compose file", () => { +test("Add suffix to service names with container_name in compose file", () => { const composeData = load(composeFile) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToServiceNames( + const updatedComposeData = addSuffixToServiceNames( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; // Verificar que el nombre del contenedor ha cambiado correctamente - expect(actualComposeData.services?.[`web-${prefix}`]?.container_name).toBe( - `web_container-${prefix}`, + expect(actualComposeData.services?.[`web-${suffix}`]?.container_name).toBe( + `web_container-${suffix}`, ); // Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe - expect(actualComposeData.services).toHaveProperty(`web-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`web-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("web"); // Verificar que la configuración de la imagen sigue igual - expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`web-${suffix}`]?.image).toBe( "nginx:latest", ); - expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe( "myapi:latest", ); }); diff --git a/apps/dokploy/__test__/compose/service/service-depends-on.test.ts b/apps/dokploy/__test__/compose/service/service-depends-on.test.ts index e339ee65..02d88591 100644 --- a/apps/dokploy/__test__/compose/service/service-depends-on.test.ts +++ b/apps/dokploy/__test__/compose/service/service-depends-on.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToServiceNames } from "@/server/utils/docker/compose/service"; +import { addSuffixToServiceNames } from "@/server/utils/docker/compose/service"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -32,49 +32,49 @@ networks: driver: bridge `; -test("Add prefix to service names with depends_on (array) in compose file", () => { +test("Add suffix to service names with depends_on (array) in compose file", () => { const composeData = load(composeFile4) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToServiceNames( + const updatedComposeData = addSuffixToServiceNames( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; // Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe - expect(actualComposeData.services).toHaveProperty(`web-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`web-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("web"); // Verificar que la configuración de la imagen sigue igual - expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`web-${suffix}`]?.image).toBe( "nginx:latest", ); - expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe( "myapi:latest", ); // Verificar que los nombres en depends_on tienen el prefijo - expect(actualComposeData.services?.[`web-${prefix}`]?.depends_on).toContain( - `db-${prefix}`, + expect(actualComposeData.services?.[`web-${suffix}`]?.depends_on).toContain( + `db-${suffix}`, ); - expect(actualComposeData.services?.[`web-${prefix}`]?.depends_on).toContain( - `api-${prefix}`, + expect(actualComposeData.services?.[`web-${suffix}`]?.depends_on).toContain( + `api-${suffix}`, ); // Verificar que los servicios `db` y `api` también tienen el prefijo - expect(actualComposeData.services).toHaveProperty(`db-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`db-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("db"); - expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`db-${suffix}`]?.image).toBe( "postgres:latest", ); - expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`api-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("api"); - expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe( "myapi:latest", ); }); @@ -102,49 +102,49 @@ networks: driver: bridge `; -test("Add prefix to service names with depends_on (object) in compose file", () => { +test("Add suffix to service names with depends_on (object) in compose file", () => { const composeData = load(composeFile5) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToServiceNames( + const updatedComposeData = addSuffixToServiceNames( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; // Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe - expect(actualComposeData.services).toHaveProperty(`web-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`web-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("web"); // Verificar que la configuración de la imagen sigue igual - expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`web-${suffix}`]?.image).toBe( "nginx:latest", ); - expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe( "myapi:latest", ); // Verificar que los nombres en depends_on tienen el prefijo - const webDependsOn = actualComposeData.services?.[`web-${prefix}`] + const webDependsOn = actualComposeData.services?.[`web-${suffix}`] ?.depends_on as Record; - expect(webDependsOn).toHaveProperty(`db-${prefix}`); - expect(webDependsOn).toHaveProperty(`api-${prefix}`); - expect(webDependsOn[`db-${prefix}`].condition).toBe("service_healthy"); - expect(webDependsOn[`api-${prefix}`].condition).toBe("service_started"); + expect(webDependsOn).toHaveProperty(`db-${suffix}`); + expect(webDependsOn).toHaveProperty(`api-${suffix}`); + expect(webDependsOn[`db-${suffix}`].condition).toBe("service_healthy"); + expect(webDependsOn[`api-${suffix}`].condition).toBe("service_started"); // Verificar que los servicios `db` y `api` también tienen el prefijo - expect(actualComposeData.services).toHaveProperty(`db-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`db-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("db"); - expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`db-${suffix}`]?.image).toBe( "postgres:latest", ); - expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`api-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("api"); - expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe( "myapi:latest", ); }); diff --git a/apps/dokploy/__test__/compose/service/service-extends.test.ts b/apps/dokploy/__test__/compose/service/service-extends.test.ts index e8f31aab..5590005b 100644 --- a/apps/dokploy/__test__/compose/service/service-extends.test.ts +++ b/apps/dokploy/__test__/compose/service/service-extends.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToServiceNames } from "@/server/utils/docker/compose/service"; +import { addSuffixToServiceNames } from "@/server/utils/docker/compose/service"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -30,41 +30,41 @@ networks: driver: bridge `; -test("Add prefix to service names with extends (string) in compose file", () => { +test("Add suffix to service names with extends (string) in compose file", () => { const composeData = load(composeFile6) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToServiceNames( + const updatedComposeData = addSuffixToServiceNames( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; // Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe - expect(actualComposeData.services).toHaveProperty(`web-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`web-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("web"); // Verificar que la configuración de la imagen sigue igual - expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`web-${suffix}`]?.image).toBe( "nginx:latest", ); - expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe( "myapi:latest", ); // Verificar que el nombre en extends tiene el prefijo - expect(actualComposeData.services?.[`web-${prefix}`]?.extends).toBe( - `base_service-${prefix}`, + expect(actualComposeData.services?.[`web-${suffix}`]?.extends).toBe( + `base_service-${suffix}`, ); // Verificar que el servicio `base_service` también tiene el prefijo - expect(actualComposeData.services).toHaveProperty(`base_service-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`base_service-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("base_service"); - expect(actualComposeData.services?.[`base_service-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`base_service-${suffix}`]?.image).toBe( "base:latest", ); }); @@ -90,42 +90,42 @@ networks: driver: bridge `; -test("Add prefix to service names with extends (object) in compose file", () => { +test("Add suffix to service names with extends (object) in compose file", () => { const composeData = load(composeFile7) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToServiceNames( + const updatedComposeData = addSuffixToServiceNames( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; // Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe - expect(actualComposeData.services).toHaveProperty(`web-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`web-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("web"); // Verificar que la configuración de la imagen sigue igual - expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`web-${suffix}`]?.image).toBe( "nginx:latest", ); - expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe( "myapi:latest", ); // Verificar que el nombre en extends.service tiene el prefijo - const webExtends = actualComposeData.services?.[`web-${prefix}`]?.extends; + const webExtends = actualComposeData.services?.[`web-${suffix}`]?.extends; if (typeof webExtends !== "string") { - expect(webExtends?.service).toBe(`base_service-${prefix}`); + expect(webExtends?.service).toBe(`base_service-${suffix}`); } // Verificar que el servicio `base_service` también tiene el prefijo - expect(actualComposeData.services).toHaveProperty(`base_service-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`base_service-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("base_service"); - expect(actualComposeData.services?.[`base_service-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`base_service-${suffix}`]?.image).toBe( "base:latest", ); }); diff --git a/apps/dokploy/__test__/compose/service/service-links.test.ts b/apps/dokploy/__test__/compose/service/service-links.test.ts index 08252649..70697e29 100644 --- a/apps/dokploy/__test__/compose/service/service-links.test.ts +++ b/apps/dokploy/__test__/compose/service/service-links.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToServiceNames } from "@/server/utils/docker/compose/service"; +import { addSuffixToServiceNames } from "@/server/utils/docker/compose/service"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -31,46 +31,46 @@ networks: driver: bridge `; -test("Add prefix to service names with links in compose file", () => { +test("Add suffix to service names with links in compose file", () => { const composeData = load(composeFile2) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToServiceNames( + const updatedComposeData = addSuffixToServiceNames( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; // Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe - expect(actualComposeData.services).toHaveProperty(`web-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`web-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("web"); // Verificar que la configuración de la imagen sigue igual - expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`web-${suffix}`]?.image).toBe( "nginx:latest", ); - expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe( "myapi:latest", ); // Verificar que los nombres en links tienen el prefijo - expect(actualComposeData.services?.[`web-${prefix}`]?.links).toContain( - `db-${prefix}`, + expect(actualComposeData.services?.[`web-${suffix}`]?.links).toContain( + `db-${suffix}`, ); // Verificar que los servicios `db` y `api` también tienen el prefijo - expect(actualComposeData.services).toHaveProperty(`db-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`db-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("db"); - expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`db-${suffix}`]?.image).toBe( "postgres:latest", ); - expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`api-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("api"); - expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe( "myapi:latest", ); }); diff --git a/apps/dokploy/__test__/compose/service/service-names.test.ts b/apps/dokploy/__test__/compose/service/service-names.test.ts index 0f071b2e..95910ef0 100644 --- a/apps/dokploy/__test__/compose/service/service-names.test.ts +++ b/apps/dokploy/__test__/compose/service/service-names.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToServiceNames } from "@/server/utils/docker/compose/service"; +import { addSuffixToServiceNames } from "@/server/utils/docker/compose/service"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -26,23 +26,23 @@ networks: driver: bridge `; -test("Add prefix to service names in compose file", () => { +test("Add suffix to service names in compose file", () => { const composeData = load(composeFile) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToServiceNames( + const updatedComposeData = addSuffixToServiceNames( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; // Verificar que los nombres de los servicios han cambiado correctamente - expect(actualComposeData.services).toHaveProperty(`web-${prefix}`); - expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`web-${suffix}`); + expect(actualComposeData.services).toHaveProperty(`api-${suffix}`); // Verificar que las claves originales no existen expect(actualComposeData.services).not.toHaveProperty("web"); expect(actualComposeData.services).not.toHaveProperty("api"); diff --git a/apps/dokploy/__test__/compose/service/service.test.ts b/apps/dokploy/__test__/compose/service/service.test.ts index 113576ae..02ccaea2 100644 --- a/apps/dokploy/__test__/compose/service/service.test.ts +++ b/apps/dokploy/__test__/compose/service/service.test.ts @@ -1,6 +1,6 @@ import { - addPrefixToAllServiceNames, - addPrefixToServiceNames, + addSuffixToAllServiceNames, + addSuffixToServiceNames, } from "@/server/utils/docker/compose/service"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; @@ -70,17 +70,17 @@ networks: driver: bridge `); -test("Add prefix to all service names in compose file", () => { +test("Add suffix to all service names in compose file", () => { const composeData = load(composeFileCombinedAllCases) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; if (!composeData.services) { return; } - const updatedComposeData = addPrefixToServiceNames( + const updatedComposeData = addSuffixToServiceNames( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; @@ -175,11 +175,11 @@ networks: driver: bridge `) as ComposeSpecification; -test("Add prefix to all service names in compose file 1", () => { +test("Add suffix to all service names in compose file 1", () => { const composeData = load(composeFile1) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllServiceNames(composeData, prefix); + const updatedComposeData = addSuffixToAllServiceNames(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFile1); }); @@ -270,11 +270,11 @@ networks: driver: bridge `) as ComposeSpecification; -test("Add prefix to all service names in compose file 2", () => { +test("Add suffix to all service names in compose file 2", () => { const composeData = load(composeFile2) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllServiceNames(composeData, prefix); + const updatedComposeData = addSuffixToAllServiceNames(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFile2); }); @@ -365,11 +365,11 @@ networks: driver: bridge `) as ComposeSpecification; -test("Add prefix to all service names in compose file 3", () => { +test("Add suffix to all service names in compose file 3", () => { const composeData = load(composeFile3) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllServiceNames(composeData, prefix); + const updatedComposeData = addSuffixToAllServiceNames(composeData, suffix); expect(updatedComposeData).toEqual(expectedComposeFile3); }); diff --git a/apps/dokploy/__test__/compose/service/sevice-volumes-from.test.ts b/apps/dokploy/__test__/compose/service/sevice-volumes-from.test.ts index 00d75fe8..49c2b55e 100644 --- a/apps/dokploy/__test__/compose/service/sevice-volumes-from.test.ts +++ b/apps/dokploy/__test__/compose/service/sevice-volumes-from.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToServiceNames } from "@/server/utils/docker/compose/service"; +import { addSuffixToServiceNames } from "@/server/utils/docker/compose/service"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -35,44 +35,44 @@ networks: driver: bridge `; -test("Add prefix to service names with volumes_from in compose file", () => { +test("Add suffix to service names with volumes_from in compose file", () => { const composeData = load(composeFile3) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToServiceNames( + const updatedComposeData = addSuffixToServiceNames( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; // Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe - expect(actualComposeData.services).toHaveProperty(`web-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`web-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("web"); // Verificar que la configuración de la imagen sigue igual - expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`web-${suffix}`]?.image).toBe( "nginx:latest", ); - expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe( "myapi:latest", ); // Verificar que los nombres en volumes_from tienen el prefijo - expect(actualComposeData.services?.[`web-${prefix}`]?.volumes_from).toContain( - `shared-${prefix}`, + expect(actualComposeData.services?.[`web-${suffix}`]?.volumes_from).toContain( + `shared-${suffix}`, ); - expect(actualComposeData.services?.[`api-${prefix}`]?.volumes_from).toContain( - `shared-${prefix}`, + expect(actualComposeData.services?.[`api-${suffix}`]?.volumes_from).toContain( + `shared-${suffix}`, ); // Verificar que el servicio shared también tiene el prefijo - expect(actualComposeData.services).toHaveProperty(`shared-${prefix}`); + expect(actualComposeData.services).toHaveProperty(`shared-${suffix}`); expect(actualComposeData.services).not.toHaveProperty("shared"); - expect(actualComposeData.services?.[`shared-${prefix}`]?.image).toBe( + expect(actualComposeData.services?.[`shared-${suffix}`]?.image).toBe( "busybox", ); }); diff --git a/apps/dokploy/__test__/compose/volume/volume-2.test.ts b/apps/dokploy/__test__/compose/volume/volume-2.test.ts index 57bfb761..9424bc0e 100644 --- a/apps/dokploy/__test__/compose/volume/volume-2.test.ts +++ b/apps/dokploy/__test__/compose/volume/volume-2.test.ts @@ -1,7 +1,7 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; import { - addPrefixToAllVolumes, - addPrefixToVolumesRoot, + addSuffixToAllVolumes, + addSuffixToVolumesRoot, } from "@/server/utils/docker/compose/volume"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; @@ -142,15 +142,15 @@ test("Generate random hash with 8 characters", () => { // Docker compose needs unique names for services, volumes, networks and containers // So base on a input which is a dockercompose file, it should replace the name with a hash and return a new dockercompose file -test("Add prefix to volumes root property", () => { +test("Add suffix to volumes root property", () => { const composeData = load(composeFile) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.volumes) { return; } - const volumes = addPrefixToVolumesRoot(composeData.volumes, prefix); + const volumes = addSuffixToVolumesRoot(composeData.volumes, suffix); // { // 'db-data-af045046': { driver: 'local' }, @@ -160,15 +160,15 @@ test("Add prefix to volumes root property", () => { expect(volumes).toBeDefined(); for (const volumeKey of Object.keys(volumes)) { - expect(volumeKey).toContain(`-${prefix}`); + expect(volumeKey).toContain(`-${suffix}`); } }); -test("Expect to change the prefix in all the possible places", () => { +test("Expect to change the suffix in all the possible places", () => { const composeData = load(composeFile) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllVolumes(composeData, prefix); + const updatedComposeData = addSuffixToAllVolumes(composeData, suffix); expect(updatedComposeData).toEqual(expectedDockerCompose); }); @@ -217,11 +217,11 @@ volumes: mongo-data-testhash: `) as ComposeSpecification; -test("Expect to change the prefix in all the possible places (2 Try)", () => { +test("Expect to change the suffix in all the possible places (2 Try)", () => { const composeData = load(composeFile2) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllVolumes(composeData, prefix); + const updatedComposeData = addSuffixToAllVolumes(composeData, suffix); expect(updatedComposeData).toEqual(expectedDockerCompose2); }); @@ -270,11 +270,11 @@ volumes: mongo-data-testhash: `) as ComposeSpecification; -test("Expect to change the prefix in all the possible places (3 Try)", () => { +test("Expect to change the suffix in all the possible places (3 Try)", () => { const composeData = load(composeFile3) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllVolumes(composeData, prefix); + const updatedComposeData = addSuffixToAllVolumes(composeData, suffix); expect(updatedComposeData).toEqual(expectedDockerCompose3); }); @@ -1011,11 +1011,11 @@ volumes: db-config-testhash: `) as ComposeSpecification; -test("Expect to change the prefix in all the possible places (4 Try)", () => { +test("Expect to change the suffix in all the possible places (4 Try)", () => { const composeData = load(composeFileComplex) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllVolumes(composeData, prefix); + const updatedComposeData = addSuffixToAllVolumes(composeData, suffix); expect(updatedComposeData).toEqual(expectedDockerComposeComplex); }); @@ -1110,11 +1110,11 @@ volumes: db-data-testhash: `) as ComposeSpecification; -test("Expect to change the prefix in all the possible places (5 Try)", () => { +test("Expect to change the suffix in all the possible places (5 Try)", () => { const composeData = load(composeFileExample1) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllVolumes(composeData, prefix); + const updatedComposeData = addSuffixToAllVolumes(composeData, suffix); expect(updatedComposeData).toEqual(expectedDockerComposeExample1); }); diff --git a/apps/dokploy/__test__/compose/volume/volume-root.test.ts b/apps/dokploy/__test__/compose/volume/volume-root.test.ts index 6b87f2ca..6c1f5d10 100644 --- a/apps/dokploy/__test__/compose/volume/volume-root.test.ts +++ b/apps/dokploy/__test__/compose/volume/volume-root.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToVolumesRoot } from "@/server/utils/docker/compose/volume"; +import { addSuffixToVolumesRoot } from "@/server/utils/docker/compose/volume"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -29,18 +29,18 @@ test("Generate random hash with 8 characters", () => { expect(hash.length).toBe(8); }); -test("Add prefix to volumes in root property", () => { +test("Add suffix to volumes in root property", () => { const composeData = load(composeFile) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.volumes) { return; } - const volumes = addPrefixToVolumesRoot(composeData.volumes, prefix); + const volumes = addSuffixToVolumesRoot(composeData.volumes, suffix); expect(volumes).toBeDefined(); for (const volumeKey of Object.keys(volumes)) { - expect(volumeKey).toContain(`-${prefix}`); + expect(volumeKey).toContain(`-${suffix}`); expect(volumes[volumeKey]).toBeDefined(); } }); @@ -67,18 +67,18 @@ networks: driver: bridge `; -test("Add prefix to volumes in root property (Case 2)", () => { +test("Add suffix to volumes in root property (Case 2)", () => { const composeData = load(composeFile2) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.volumes) { return; } - const volumes = addPrefixToVolumesRoot(composeData.volumes, prefix); + const volumes = addSuffixToVolumesRoot(composeData.volumes, suffix); expect(volumes).toBeDefined(); for (const volumeKey of Object.keys(volumes)) { - expect(volumeKey).toContain(`-${prefix}`); + expect(volumeKey).toContain(`-${suffix}`); expect(volumes[volumeKey]).toBeDefined(); } }); @@ -101,19 +101,19 @@ networks: driver: bridge `; -test("Add prefix to volumes in root property (Case 3)", () => { +test("Add suffix to volumes in root property (Case 3)", () => { const composeData = load(composeFile3) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData?.volumes) { return; } - const volumes = addPrefixToVolumesRoot(composeData.volumes, prefix); + const volumes = addSuffixToVolumesRoot(composeData.volumes, suffix); expect(volumes).toBeDefined(); for (const volumeKey of Object.keys(volumes)) { - expect(volumeKey).toContain(`-${prefix}`); + expect(volumeKey).toContain(`-${suffix}`); expect(volumes[volumeKey]).toBeDefined(); } }); @@ -179,15 +179,15 @@ volumes: `) as ComposeSpecification; -test("Add prefix to volumes in root property", () => { +test("Add suffix to volumes in root property", () => { const composeData = load(composeFile4) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; if (!composeData?.volumes) { return; } - const volumes = addPrefixToVolumesRoot(composeData.volumes, prefix); + const volumes = addSuffixToVolumesRoot(composeData.volumes, suffix); const updatedComposeData = { ...composeData, volumes }; // Verificar que el resultado coincide con el archivo esperado diff --git a/apps/dokploy/__test__/compose/volume/volume-services.test.ts b/apps/dokploy/__test__/compose/volume/volume-services.test.ts index 331c3bf1..1940a4f2 100644 --- a/apps/dokploy/__test__/compose/volume/volume-services.test.ts +++ b/apps/dokploy/__test__/compose/volume/volume-services.test.ts @@ -1,5 +1,5 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; -import { addPrefixToVolumesInServices } from "@/server/utils/docker/compose/volume"; +import { addSuffixToVolumesInServices } from "@/server/utils/docker/compose/volume"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; @@ -21,22 +21,22 @@ services: - db_data:/var/lib/postgresql/data `; -test("Add prefix to volumes declared directly in services", () => { +test("Add suffix to volumes declared directly in services", () => { const composeData = load(composeFile1) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToVolumesInServices( + const updatedComposeData = addSuffixToVolumesInServices( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; expect(actualComposeData.services?.db?.volumes).toContain( - `db_data-${prefix}:/var/lib/postgresql/data`, + `db_data-${suffix}:/var/lib/postgresql/data`, ); }); @@ -56,25 +56,25 @@ volumes: driver: local `; -test("Add prefix to volumes declared directly in services (Case 2)", () => { +test("Add suffix to volumes declared directly in services (Case 2)", () => { const composeData = load(composeFileTypeVolume) as ComposeSpecification; - const prefix = generateRandomHash(); + const suffix = generateRandomHash(); if (!composeData.services) { return; } - const updatedComposeData = addPrefixToVolumesInServices( + const updatedComposeData = addSuffixToVolumesInServices( composeData.services, - prefix, + suffix, ); const actualComposeData = { ...composeData, services: updatedComposeData }; expect(actualComposeData.services?.db?.volumes).toEqual([ { type: "volume", - source: `db-test-${prefix}`, + source: `db-test-${suffix}`, target: "/var/lib/postgresql/data", }, ]); diff --git a/apps/dokploy/__test__/compose/volume/volume.test.ts b/apps/dokploy/__test__/compose/volume/volume.test.ts index 98a23588..8d799bcd 100644 --- a/apps/dokploy/__test__/compose/volume/volume.test.ts +++ b/apps/dokploy/__test__/compose/volume/volume.test.ts @@ -1,7 +1,7 @@ import { generateRandomHash } from "@/server/utils/docker/compose"; import { - addPrefixToAllVolumes, - addPrefixToVolumesInServices, + addSuffixToAllVolumes, + addSuffixToVolumesInServices, } from "@/server/utils/docker/compose/volume"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; @@ -47,12 +47,12 @@ volumes: driver: local `) as ComposeSpecification; -test("Add prefix to volumes with type: volume in services", () => { +test("Add suffix to volumes with type: volume in services", () => { const composeData = load(composeFileTypeVolume) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllVolumes(composeData, prefix); + const updatedComposeData = addSuffixToAllVolumes(composeData, suffix); const actualComposeData = { ...composeData, ...updatedComposeData }; expect(actualComposeData).toEqual(expectedComposeFileTypeVolume); @@ -96,12 +96,12 @@ volumes: driver: local `) as ComposeSpecification; -test("Add prefix to mixed volumes in services", () => { +test("Add suffix to mixed volumes in services", () => { const composeData = load(composeFileTypeVolume1) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllVolumes(composeData, prefix); + const updatedComposeData = addSuffixToAllVolumes(composeData, suffix); const actualComposeData = { ...composeData, ...updatedComposeData }; expect(actualComposeData).toEqual(expectedComposeFileTypeVolume1); @@ -157,12 +157,12 @@ volumes: device: /path/to/app/logs `) as ComposeSpecification; -test("Add prefix to complex volume configurations in services", () => { +test("Add suffix to complex volume configurations in services", () => { const composeData = load(composeFileTypeVolume2) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllVolumes(composeData, prefix); + const updatedComposeData = addSuffixToAllVolumes(composeData, suffix); const actualComposeData = { ...composeData, ...updatedComposeData }; expect(actualComposeData).toEqual(expectedComposeFileTypeVolume2); @@ -276,12 +276,12 @@ volumes: device: /path/to/shared/logs `) as ComposeSpecification; -test("Add prefix to complex nested volumes configuration in services", () => { +test("Add suffix to complex nested volumes configuration in services", () => { const composeData = load(composeFileTypeVolume3) as ComposeSpecification; - const prefix = "testhash"; + const suffix = "testhash"; - const updatedComposeData = addPrefixToAllVolumes(composeData, prefix); + const updatedComposeData = addSuffixToAllVolumes(composeData, suffix); const actualComposeData = { ...composeData, ...updatedComposeData }; expect(actualComposeData).toEqual(expectedComposeFileTypeVolume3); diff --git a/apps/dokploy/__test__/traefik/traefik.test.ts b/apps/dokploy/__test__/traefik/traefik.test.ts index 7ca9f169..bc62cb62 100644 --- a/apps/dokploy/__test__/traefik/traefik.test.ts +++ b/apps/dokploy/__test__/traefik/traefik.test.ts @@ -107,7 +107,7 @@ test("Web entrypoint on http domain", async () => { ); expect(router.middlewares).not.toContain("redirect-to-https"); - expect(router.rule).not.toContain("PathPrefix"); + expect(router.rule).not.toContain("PathSuffix"); }); test("Web entrypoint on http domain with custom path", async () => { @@ -117,7 +117,7 @@ test("Web entrypoint on http domain with custom path", async () => { "web", ); - expect(router.rule).toContain("PathPrefix(`/foo`)"); + expect(router.rule).toContain("PathSuffix(`/foo`)"); }); test("Web entrypoint on http domain with redirect", async () => { diff --git a/apps/dokploy/components/dashboard/compose/general/randomize-compose.tsx b/apps/dokploy/components/dashboard/compose/general/randomize-compose.tsx index 2fc59f12..2c6184c8 100644 --- a/apps/dokploy/components/dashboard/compose/general/randomize-compose.tsx +++ b/apps/dokploy/components/dashboard/compose/general/randomize-compose.tsx @@ -11,13 +11,13 @@ import { DialogTrigger, } from "@/components/ui/dialog"; import { + Form, + FormControl, + FormDescription, FormField, FormItem, FormLabel, - FormControl, - FormDescription, FormMessage, - Form, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { @@ -39,7 +39,7 @@ interface Props { } const schema = z.object({ - prefix: z.string(), + suffix: z.string(), randomize: z.boolean().optional(), }); @@ -61,18 +61,18 @@ export const RandomizeCompose = ({ composeId }: Props) => { const form = useForm({ defaultValues: { - prefix: "", + suffix: "", randomize: false, }, resolver: zodResolver(schema), }); - const prefix = form.watch("prefix"); + const suffix = form.watch("suffix"); useEffect(() => { if (data) { form.reset({ - prefix: data?.prefix || "", + suffix: data?.suffix || "", randomize: data?.randomize || false, }); } @@ -81,7 +81,7 @@ export const RandomizeCompose = ({ composeId }: Props) => { const onSubmit = async (formData: Schema) => { await updateCompose({ composeId, - prefix: formData?.prefix || "", + suffix: formData?.suffix || "", randomize: formData?.randomize || false, }) .then(async (data) => { @@ -97,7 +97,7 @@ export const RandomizeCompose = ({ composeId }: Props) => { const randomizeCompose = async () => { await mutateAsync({ composeId, - prefix, + suffix, }) .then(async (data) => { await utils.project.all.invalidate(); @@ -127,7 +127,7 @@ export const RandomizeCompose = ({ composeId }: Props) => {
- This will randomize the compose file and will add a prefix to the + This will randomize the compose file and will add a suffix to the property to avoid conflicts
    @@ -163,13 +163,13 @@ export const RandomizeCompose = ({ composeId }: Props) => {
    ( - Prefix + Suffix diff --git a/apps/dokploy/drizzle/0035_tired_kinsey_walden.sql b/apps/dokploy/drizzle/0035_cool_gravity.sql similarity index 61% rename from apps/dokploy/drizzle/0035_tired_kinsey_walden.sql rename to apps/dokploy/drizzle/0035_cool_gravity.sql index b5ac9328..9749285d 100644 --- a/apps/dokploy/drizzle/0035_tired_kinsey_walden.sql +++ b/apps/dokploy/drizzle/0035_cool_gravity.sql @@ -1,2 +1,2 @@ -ALTER TABLE "compose" ADD COLUMN "prefix" text DEFAULT '' NOT NULL;--> statement-breakpoint +ALTER TABLE "compose" ADD COLUMN "suffix" text DEFAULT '' NOT NULL;--> statement-breakpoint ALTER TABLE "compose" ADD COLUMN "randomize" boolean DEFAULT false NOT NULL; \ No newline at end of file diff --git a/apps/dokploy/drizzle/meta/0035_snapshot.json b/apps/dokploy/drizzle/meta/0035_snapshot.json index 80b4e4a8..970edd40 100644 --- a/apps/dokploy/drizzle/meta/0035_snapshot.json +++ b/apps/dokploy/drizzle/meta/0035_snapshot.json @@ -1,5 +1,5 @@ { - "id": "51601bf9-6706-4a79-9029-cbad20ea9e02", + "id": "bb060896-7fc0-4bf3-b579-65f118769de0", "prevId": "6a7ce86e-f628-4786-ab30-e160dcdb0a39", "version": "6", "dialect": "postgresql", @@ -2602,8 +2602,8 @@ "notNull": true, "default": "'./docker-compose.yml'" }, - "prefix": { - "name": "prefix", + "suffix": { + "name": "suffix", "type": "text", "primaryKey": false, "notNull": true, diff --git a/apps/dokploy/drizzle/meta/_journal.json b/apps/dokploy/drizzle/meta/_journal.json index 2bd9e2b3..c945eb37 100644 --- a/apps/dokploy/drizzle/meta/_journal.json +++ b/apps/dokploy/drizzle/meta/_journal.json @@ -250,8 +250,8 @@ { "idx": 35, "version": "6", - "when": 1725421774684, - "tag": "0035_tired_kinsey_walden", + "when": 1725429324584, + "tag": "0035_cool_gravity", "breakpoints": true } ] diff --git a/apps/dokploy/server/api/routers/compose.ts b/apps/dokploy/server/api/routers/compose.ts index 82dee89a..26be7fca 100644 --- a/apps/dokploy/server/api/routers/compose.ts +++ b/apps/dokploy/server/api/routers/compose.ts @@ -144,7 +144,7 @@ export const composeRouter = createTRPCRouter({ randomizeCompose: protectedProcedure .input(apiRandomizeCompose) .mutation(async ({ input }) => { - return await randomizeComposeFile(input.composeId, input.prefix); + return await randomizeComposeFile(input.composeId, input.suffix); }), getConvertedCompose: protectedProcedure .input(apiFindCompose) diff --git a/apps/dokploy/server/api/services/compose.ts b/apps/dokploy/server/api/services/compose.ts index ca40e2c5..f1dadb95 100644 --- a/apps/dokploy/server/api/services/compose.ts +++ b/apps/dokploy/server/api/services/compose.ts @@ -4,6 +4,7 @@ import { db } from "@/server/db"; import { type apiCreateCompose, compose } from "@/server/db/schema"; import { generateAppName } from "@/server/db/schema/utils"; import { buildCompose } from "@/server/utils/builders/compose"; +import { randomizeSpecificationFile } from "@/server/utils/docker/compose"; import { cloneCompose, loadDockerCompose } from "@/server/utils/docker/domain"; import { sendBuildErrorNotifications } from "@/server/utils/notifications/build-error"; import { sendBuildSuccessNotifications } from "@/server/utils/notifications/build-success"; @@ -19,7 +20,6 @@ import { eq } from "drizzle-orm"; import { getDokployUrl } from "./admin"; import { createDeploymentCompose, updateDeploymentStatus } from "./deployment"; import { validUniqueServerAppName } from "./project"; -import { randomizeSpecificationFile } from "@/server/utils/docker/compose"; export type Compose = typeof compose.$inferSelect; @@ -123,7 +123,7 @@ export const loadServices = async ( if (compose.randomize && composeData) { const randomizedCompose = randomizeSpecificationFile( composeData, - compose.prefix, + compose.suffix, ); composeData = randomizedCompose; } diff --git a/apps/dokploy/server/db/schema/compose.ts b/apps/dokploy/server/db/schema/compose.ts index c8de5289..f2ab084a 100644 --- a/apps/dokploy/server/db/schema/compose.ts +++ b/apps/dokploy/server/db/schema/compose.ts @@ -64,7 +64,7 @@ export const compose = pgTable("compose", { command: text("command").notNull().default(""), // composePath: text("composePath").notNull().default("./docker-compose.yml"), - prefix: text("prefix").notNull().default(""), + suffix: text("suffix").notNull().default(""), randomize: boolean("randomize").notNull().default(false), composeStatus: applicationStatus("composeStatus").notNull().default("idle"), projectId: text("projectId") @@ -159,6 +159,6 @@ export const apiRandomizeCompose = createSchema composeId: true, }) .extend({ - prefix: z.string().optional(), + suffix: z.string().optional(), composeId: z.string().min(1), }); diff --git a/apps/dokploy/server/utils/builders/compose.ts b/apps/dokploy/server/utils/builders/compose.ts index 664f59ee..10e56aba 100644 --- a/apps/dokploy/server/utils/builders/compose.ts +++ b/apps/dokploy/server/utils/builders/compose.ts @@ -110,7 +110,7 @@ const createEnvFile = (compose: ComposeNested) => { } if (compose.randomize) { - envContent += `\nCOMPOSE_PREFIX=${compose.prefix}`; + envContent += `\nCOMPOSE_PREFIX=${compose.suffix}`; } const envFileContent = prepareEnvironmentVariables(envContent).join("\n"); diff --git a/apps/dokploy/server/utils/docker/compose.ts b/apps/dokploy/server/utils/docker/compose.ts index 42a7c0f7..8b9f8b7c 100644 --- a/apps/dokploy/server/utils/docker/compose.ts +++ b/apps/dokploy/server/utils/docker/compose.ts @@ -1,11 +1,11 @@ import crypto from "node:crypto"; import { findComposeById } from "@/server/api/services/compose"; import { dump, load } from "js-yaml"; -import { addPrefixToAllConfigs } from "./compose/configs"; -import { addPrefixToAllNetworks } from "./compose/network"; -import { addPrefixToAllSecrets } from "./compose/secrets"; -import { addPrefixToAllServiceNames } from "./compose/service"; -import { addPrefixToAllVolumes } from "./compose/volume"; +import { addSuffixToAllConfigs } from "./compose/configs"; +import { addSuffixToAllNetworks } from "./compose/network"; +import { addSuffixToAllSecrets } from "./compose/secrets"; +import { addSuffixToAllServiceNames } from "./compose/service"; +import { addSuffixToAllVolumes } from "./compose/volume"; import type { ComposeSpecification } from "./types"; export const generateRandomHash = (): string => { @@ -14,43 +14,43 @@ export const generateRandomHash = (): string => { export const randomizeComposeFile = async ( composeId: string, - prefix?: string, + suffix?: string, ) => { const compose = await findComposeById(composeId); const composeFile = compose.composeFile; const composeData = load(composeFile) as ComposeSpecification; - const randomPrefix = prefix || generateRandomHash(); + const randomSuffix = suffix || generateRandomHash(); - const newComposeFile = addPrefixToAllProperties(composeData, randomPrefix); + const newComposeFile = addSuffixToAllProperties(composeData, randomSuffix); return dump(newComposeFile); }; export const randomizeSpecificationFile = ( composeSpec: ComposeSpecification, - prefix?: string, + suffix?: string, ) => { - if (!prefix) { + if (!suffix) { return composeSpec; } - const newComposeFile = addPrefixToAllProperties(composeSpec, prefix); + const newComposeFile = addSuffixToAllProperties(composeSpec, suffix); return newComposeFile; }; -export const addPrefixToAllProperties = ( +export const addSuffixToAllProperties = ( composeData: ComposeSpecification, - prefix: string, + suffix: string, ): ComposeSpecification => { let updatedComposeData = { ...composeData }; - updatedComposeData = addPrefixToAllServiceNames(updatedComposeData, prefix); + updatedComposeData = addSuffixToAllServiceNames(updatedComposeData, suffix); - updatedComposeData = addPrefixToAllVolumes(updatedComposeData, prefix); + updatedComposeData = addSuffixToAllVolumes(updatedComposeData, suffix); - updatedComposeData = addPrefixToAllNetworks(updatedComposeData, prefix); - updatedComposeData = addPrefixToAllConfigs(updatedComposeData, prefix); + updatedComposeData = addSuffixToAllNetworks(updatedComposeData, suffix); + updatedComposeData = addSuffixToAllConfigs(updatedComposeData, suffix); - updatedComposeData = addPrefixToAllSecrets(updatedComposeData, prefix); + updatedComposeData = addSuffixToAllSecrets(updatedComposeData, suffix); return updatedComposeData; }; diff --git a/apps/dokploy/server/utils/docker/compose/configs.ts b/apps/dokploy/server/utils/docker/compose/configs.ts index 17bfb171..b985db1a 100644 --- a/apps/dokploy/server/utils/docker/compose/configs.ts +++ b/apps/dokploy/server/utils/docker/compose/configs.ts @@ -5,23 +5,23 @@ import type { DefinitionsService, } from "../types"; -export const addPrefixToConfigsRoot = ( +export const addSuffixToConfigsRoot = ( configs: { [key: string]: DefinitionsConfig }, - prefix: string, + suffix: string, ): { [key: string]: DefinitionsConfig } => { const newConfigs: { [key: string]: DefinitionsConfig } = {}; _.forEach(configs, (config, configName) => { - const newConfigName = `${configName}-${prefix}`; + const newConfigName = `${configName}-${suffix}`; newConfigs[newConfigName] = _.cloneDeep(config); }); return newConfigs; }; -export const addPrefixToConfigsInServices = ( +export const addSuffixToConfigsInServices = ( services: { [key: string]: DefinitionsService }, - prefix: string, + suffix: string, ): { [key: string]: DefinitionsService } => { const newServices: { [key: string]: DefinitionsService } = {}; @@ -32,12 +32,12 @@ export const addPrefixToConfigsInServices = ( if (_.has(newServiceConfig, "configs")) { newServiceConfig.configs = _.map(newServiceConfig.configs, (config) => { if (_.isString(config)) { - return `${config}-${prefix}`; + return `${config}-${suffix}`; } if (_.isObject(config) && config.source) { return { ...config, - source: `${config.source}-${prefix}`, + source: `${config.source}-${suffix}`, }; } return config; @@ -50,22 +50,22 @@ export const addPrefixToConfigsInServices = ( return newServices; }; -export const addPrefixToAllConfigs = ( +export const addSuffixToAllConfigs = ( composeData: ComposeSpecification, - prefix: string, + suffix: string, ): ComposeSpecification => { const updatedComposeData = { ...composeData }; if (composeData?.configs) { - updatedComposeData.configs = addPrefixToConfigsRoot( + updatedComposeData.configs = addSuffixToConfigsRoot( composeData.configs, - prefix, + suffix, ); } if (composeData?.services) { - updatedComposeData.services = addPrefixToConfigsInServices( + updatedComposeData.services = addSuffixToConfigsInServices( composeData.services, - prefix, + suffix, ); } diff --git a/apps/dokploy/server/utils/docker/compose/network.ts b/apps/dokploy/server/utils/docker/compose/network.ts index c52f1368..1245fb60 100644 --- a/apps/dokploy/server/utils/docker/compose/network.ts +++ b/apps/dokploy/server/utils/docker/compose/network.ts @@ -5,21 +5,21 @@ import type { DefinitionsService, } from "../types"; -export const addPrefixToNetworksRoot = ( +export const addSuffixToNetworksRoot = ( networks: { [key: string]: DefinitionsNetwork }, - prefix: string, + suffix: string, ): { [key: string]: DefinitionsNetwork } => { return _.mapKeys(networks, (_value, key) => { if (key === "dokploy-network") { return "dokploy-network"; } - return `${key}-${prefix}`; + return `${key}-${suffix}`; }); }; -export const addPrefixToServiceNetworks = ( +export const addSuffixToServiceNetworks = ( services: { [key: string]: DefinitionsService }, - prefix: string, + suffix: string, ): { [key: string]: DefinitionsService } => { return _.mapValues(services, (service) => { if (service.networks) { @@ -29,7 +29,7 @@ export const addPrefixToServiceNetworks = ( if (network === "dokploy-network") { return "dokploy-network"; } - return `${network}-${prefix}`; + return `${network}-${suffix}`; }); } else { // 2 Case @@ -37,7 +37,7 @@ export const addPrefixToServiceNetworks = ( if (key === "dokploy-network") { return "dokploy-network"; } - return `${key}-${prefix}`; + return `${key}-${suffix}`; }); // 3 Case @@ -47,7 +47,7 @@ export const addPrefixToServiceNetworks = ( if (innerKey === "aliases") { return "aliases"; } - return `${innerKey}-${prefix}`; + return `${innerKey}-${suffix}`; }); } @@ -59,23 +59,23 @@ export const addPrefixToServiceNetworks = ( }); }; -export const addPrefixToAllNetworks = ( +export const addSuffixToAllNetworks = ( composeData: ComposeSpecification, - prefix: string, + suffix: string, ): ComposeSpecification => { const updatedComposeData = { ...composeData }; if (updatedComposeData.networks) { - updatedComposeData.networks = addPrefixToNetworksRoot( + updatedComposeData.networks = addSuffixToNetworksRoot( updatedComposeData.networks, - prefix, + suffix, ); } if (updatedComposeData.services) { - updatedComposeData.services = addPrefixToServiceNetworks( + updatedComposeData.services = addSuffixToServiceNetworks( updatedComposeData.services, - prefix, + suffix, ); } diff --git a/apps/dokploy/server/utils/docker/compose/secrets.ts b/apps/dokploy/server/utils/docker/compose/secrets.ts index 2a598c1b..16c23308 100644 --- a/apps/dokploy/server/utils/docker/compose/secrets.ts +++ b/apps/dokploy/server/utils/docker/compose/secrets.ts @@ -1,21 +1,21 @@ import _ from "lodash"; import type { ComposeSpecification, DefinitionsService } from "../types"; -export const addPrefixToSecretsRoot = ( +export const addSuffixToSecretsRoot = ( secrets: ComposeSpecification["secrets"], - prefix: string, + suffix: string, ): ComposeSpecification["secrets"] => { const newSecrets: ComposeSpecification["secrets"] = {}; _.forEach(secrets, (secretConfig, secretName) => { - const newSecretName = `${secretName}-${prefix}`; + const newSecretName = `${secretName}-${suffix}`; newSecrets[newSecretName] = _.cloneDeep(secretConfig); }); return newSecrets; }; -export const addPrefixToSecretsInServices = ( +export const addSuffixToSecretsInServices = ( services: { [key: string]: DefinitionsService }, - prefix: string, + suffix: string, ): { [key: string]: DefinitionsService } => { const newServices: { [key: string]: DefinitionsService } = {}; @@ -26,12 +26,12 @@ export const addPrefixToSecretsInServices = ( if (_.has(newServiceConfig, "secrets")) { newServiceConfig.secrets = _.map(newServiceConfig.secrets, (secret) => { if (_.isString(secret)) { - return `${secret}-${prefix}`; + return `${secret}-${suffix}`; } if (_.isObject(secret) && secret.source) { return { ...secret, - source: `${secret.source}-${prefix}`, + source: `${secret.source}-${suffix}`, }; } return secret; @@ -44,23 +44,23 @@ export const addPrefixToSecretsInServices = ( return newServices; }; -export const addPrefixToAllSecrets = ( +export const addSuffixToAllSecrets = ( composeData: ComposeSpecification, - prefix: string, + suffix: string, ): ComposeSpecification => { const updatedComposeData = { ...composeData }; if (composeData?.secrets) { - updatedComposeData.secrets = addPrefixToSecretsRoot( + updatedComposeData.secrets = addSuffixToSecretsRoot( composeData.secrets, - prefix, + suffix, ); } if (composeData?.services) { - updatedComposeData.services = addPrefixToSecretsInServices( + updatedComposeData.services = addSuffixToSecretsInServices( composeData.services, - prefix, + suffix, ); } diff --git a/apps/dokploy/server/utils/docker/compose/service.ts b/apps/dokploy/server/utils/docker/compose/service.ts index ee6261c8..e22c7eb1 100644 --- a/apps/dokploy/server/utils/docker/compose/service.ts +++ b/apps/dokploy/server/utils/docker/compose/service.ts @@ -12,28 +12,28 @@ type DependsOnObject = NonNullable< : never >; -export const addPrefixToServiceNames = ( +export const addSuffixToServiceNames = ( services: { [key: string]: DefinitionsService }, - prefix: string, + suffix: string, ): { [key: string]: DefinitionsService } => { const newServices: { [key: string]: DefinitionsService } = {}; for (const [serviceName, serviceConfig] of Object.entries(services)) { - const newServiceName = `${serviceName}-${prefix}`; + const newServiceName = `${serviceName}-${suffix}`; const newServiceConfig = _.cloneDeep(serviceConfig); // Reemplazar nombres de servicios en depends_on if (newServiceConfig.depends_on) { if (Array.isArray(newServiceConfig.depends_on)) { newServiceConfig.depends_on = newServiceConfig.depends_on.map( - (dep) => `${dep}-${prefix}`, + (dep) => `${dep}-${suffix}`, ); } else { const newDependsOn: DependsOnObject = {}; for (const [depName, depConfig] of Object.entries( newServiceConfig.depends_on, )) { - newDependsOn[`${depName}-${prefix}`] = depConfig; + newDependsOn[`${depName}-${suffix}`] = depConfig; } newServiceConfig.depends_on = newDependsOn; } @@ -41,29 +41,29 @@ export const addPrefixToServiceNames = ( // Reemplazar nombre en container_name if (newServiceConfig.container_name) { - newServiceConfig.container_name = `${newServiceConfig.container_name}-${prefix}`; + newServiceConfig.container_name = `${newServiceConfig.container_name}-${suffix}`; } // Reemplazar nombres de servicios en links if (newServiceConfig.links) { newServiceConfig.links = newServiceConfig.links.map( - (link) => `${link}-${prefix}`, + (link) => `${link}-${suffix}`, ); } // Reemplazar nombres de servicios en extends if (newServiceConfig.extends) { if (typeof newServiceConfig.extends === "string") { - newServiceConfig.extends = `${newServiceConfig.extends}-${prefix}`; + newServiceConfig.extends = `${newServiceConfig.extends}-${suffix}`; } else { - newServiceConfig.extends.service = `${newServiceConfig.extends.service}-${prefix}`; + newServiceConfig.extends.service = `${newServiceConfig.extends.service}-${suffix}`; } } // Reemplazar nombres de servicios en volumes_from if (newServiceConfig.volumes_from) { newServiceConfig.volumes_from = newServiceConfig.volumes_from.map( - (vol) => `${vol}-${prefix}`, + (vol) => `${vol}-${suffix}`, ); } @@ -73,16 +73,16 @@ export const addPrefixToServiceNames = ( return newServices; }; -export const addPrefixToAllServiceNames = ( +export const addSuffixToAllServiceNames = ( composeData: ComposeSpecification, - prefix: string, + suffix: string, ): ComposeSpecification => { const updatedComposeData = { ...composeData }; if (updatedComposeData.services) { - updatedComposeData.services = addPrefixToServiceNames( + updatedComposeData.services = addSuffixToServiceNames( updatedComposeData.services, - prefix, + suffix, ); } diff --git a/apps/dokploy/server/utils/docker/compose/volume.ts b/apps/dokploy/server/utils/docker/compose/volume.ts index 87bc1248..91bde78c 100644 --- a/apps/dokploy/server/utils/docker/compose/volume.ts +++ b/apps/dokploy/server/utils/docker/compose/volume.ts @@ -6,16 +6,16 @@ import type { } from "../types"; // Función para agregar prefijo a volúmenes -export const addPrefixToVolumesRoot = ( +export const addSuffixToVolumesRoot = ( volumes: { [key: string]: DefinitionsVolume }, - prefix: string, + suffix: string, ): { [key: string]: DefinitionsVolume } => { - return _.mapKeys(volumes, (_value, key) => `${key}-${prefix}`); + return _.mapKeys(volumes, (_value, key) => `${key}-${suffix}`); }; -export const addPrefixToVolumesInServices = ( +export const addSuffixToVolumesInServices = ( services: { [key: string]: DefinitionsService }, - prefix: string, + suffix: string, ): { [key: string]: DefinitionsService } => { const newServices: { [key: string]: DefinitionsService } = {}; @@ -36,12 +36,12 @@ export const addPrefixToVolumesInServices = ( ) { return volume; } - return `${volumeName}-${prefix}:${path}`; + return `${volumeName}-${suffix}:${path}`; } if (_.isObject(volume) && volume.type === "volume" && volume.source) { return { ...volume, - source: `${volume.source}-${prefix}`, + source: `${volume.source}-${suffix}`, }; } return volume; @@ -54,23 +54,23 @@ export const addPrefixToVolumesInServices = ( return newServices; }; -export const addPrefixToAllVolumes = ( +export const addSuffixToAllVolumes = ( composeData: ComposeSpecification, - prefix: string, + suffix: string, ): ComposeSpecification => { const updatedComposeData = { ...composeData }; if (updatedComposeData.volumes) { - updatedComposeData.volumes = addPrefixToVolumesRoot( + updatedComposeData.volumes = addSuffixToVolumesRoot( updatedComposeData.volumes, - prefix, + suffix, ); } if (updatedComposeData.services) { - updatedComposeData.services = addPrefixToVolumesInServices( + updatedComposeData.services = addSuffixToVolumesInServices( updatedComposeData.services, - prefix, + suffix, ); } diff --git a/apps/dokploy/server/utils/docker/domain.ts b/apps/dokploy/server/utils/docker/domain.ts index fa7046fd..14f2a405 100644 --- a/apps/dokploy/server/utils/docker/domain.ts +++ b/apps/dokploy/server/utils/docker/domain.ts @@ -10,12 +10,12 @@ import { cloneGitRawRepository } from "../providers/git"; import { cloneRawGithubRepository } from "../providers/github"; import { cloneRawGitlabRepository } from "../providers/gitlab"; import { createComposeFileRaw } from "../providers/raw"; +import { randomizeSpecificationFile } from "./compose"; import type { ComposeSpecification, DefinitionsService, PropertiesNetworks, } from "./types"; -import { randomizeSpecificationFile } from "./compose"; export const cloneCompose = async (compose: Compose) => { if (compose.sourceType === "github") { @@ -76,7 +76,7 @@ export const writeDomainsToCompose = async ( let composeConverted = await addDomainToCompose(compose, domains); if (compose.randomize && composeConverted) { - const result = randomizeSpecificationFile(composeConverted, compose.prefix); + const result = randomizeSpecificationFile(composeConverted, compose.suffix); composeConverted = result; } @@ -101,7 +101,7 @@ export const addDomainToCompose = async ( } if (compose.randomize) { - const randomized = randomizeSpecificationFile(result, compose.prefix); + const randomized = randomizeSpecificationFile(result, compose.suffix); result = randomized; } From fca0abd585512387429423e18c2cc364d97c0803 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Wed, 4 Sep 2024 00:02:04 -0600 Subject: [PATCH 6/7] refactor: fix responsive --- .../components/dashboard/application/domains/add-domain.tsx | 2 +- .../components/dashboard/compose/domains/add-domain.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/dokploy/components/dashboard/application/domains/add-domain.tsx b/apps/dokploy/components/dashboard/application/domains/add-domain.tsx index ab7db1ef..d77796d0 100644 --- a/apps/dokploy/components/dashboard/application/domains/add-domain.tsx +++ b/apps/dokploy/components/dashboard/application/domains/add-domain.tsx @@ -161,7 +161,7 @@ export const AddDomain = ({ render={({ field }) => ( Host -
    +
    diff --git a/apps/dokploy/components/dashboard/compose/domains/add-domain.tsx b/apps/dokploy/components/dashboard/compose/domains/add-domain.tsx index 4da9404e..5e410790 100644 --- a/apps/dokploy/components/dashboard/compose/domains/add-domain.tsx +++ b/apps/dokploy/components/dashboard/compose/domains/add-domain.tsx @@ -197,7 +197,7 @@ export const AddDomainCompose = ({ render={({ field }) => ( Service Name -
    +
    From bc673d6f6730b9a0c491df3207fd0b7425d6c1d2 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Wed, 4 Sep 2024 00:08:10 -0600 Subject: [PATCH 7/7] revert: add back prefix to test --- apps/dokploy/__test__/traefik/traefik.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dokploy/__test__/traefik/traefik.test.ts b/apps/dokploy/__test__/traefik/traefik.test.ts index bc62cb62..7ca9f169 100644 --- a/apps/dokploy/__test__/traefik/traefik.test.ts +++ b/apps/dokploy/__test__/traefik/traefik.test.ts @@ -107,7 +107,7 @@ test("Web entrypoint on http domain", async () => { ); expect(router.middlewares).not.toContain("redirect-to-https"); - expect(router.rule).not.toContain("PathSuffix"); + expect(router.rule).not.toContain("PathPrefix"); }); test("Web entrypoint on http domain with custom path", async () => { @@ -117,7 +117,7 @@ test("Web entrypoint on http domain with custom path", async () => { "web", ); - expect(router.rule).toContain("PathSuffix(`/foo`)"); + expect(router.rule).toContain("PathPrefix(`/foo`)"); }); test("Web entrypoint on http domain with redirect", async () => {