Merge pull request #417 from Dokploy/fix/docker-compose-hosts

Fix/docker compose hosts
This commit is contained in:
Mauricio Siu
2024-09-04 14:20:54 -06:00
committed by GitHub
39 changed files with 4469 additions and 490 deletions

View File

@@ -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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -119,11 +119,11 @@ secrets:
file: ./db_password.txt file: ./db_password.txt
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedComposeFile1);
}); });
@@ -242,11 +242,11 @@ secrets:
file: ./db_password.txt file: ./db_password.txt
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedComposeFile2);
}); });
@@ -365,11 +365,11 @@ secrets:
file: ./service_secret.txt file: ./service_secret.txt
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedComposeFile3);
}); });
@@ -466,11 +466,11 @@ volumes:
driver: local driver: local
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedComposeFile);
}); });

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -23,19 +23,19 @@ configs:
file: ./web-config.yml 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 composeData = load(composeFile) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.configs) { if (!composeData?.configs) {
return; return;
} }
const configs = addPrefixToConfigsRoot(composeData.configs, prefix); const configs = addSuffixToConfigsRoot(composeData.configs, suffix);
expect(configs).toBeDefined(); expect(configs).toBeDefined();
for (const configKey of Object.keys(configs)) { for (const configKey of Object.keys(configs)) {
expect(configKey).toContain(`-${prefix}`); expect(configKey).toContain(`-${suffix}`);
expect(configs[configKey]).toBeDefined(); expect(configs[configKey]).toBeDefined();
} }
}); });
@@ -59,23 +59,23 @@ configs:
file: ./another-config.yml 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 composeData = load(composeFileMultipleConfigs) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.configs) { if (!composeData?.configs) {
return; return;
} }
const configs = addPrefixToConfigsRoot(composeData.configs, prefix); const configs = addSuffixToConfigsRoot(composeData.configs, suffix);
expect(configs).toBeDefined(); expect(configs).toBeDefined();
for (const configKey of Object.keys(configs)) { for (const configKey of Object.keys(configs)) {
expect(configKey).toContain(`-${prefix}`); expect(configKey).toContain(`-${suffix}`);
expect(configs[configKey]).toBeDefined(); expect(configs[configKey]).toBeDefined();
} }
expect(configs).toHaveProperty(`web-config-${prefix}`); expect(configs).toHaveProperty(`web-config-${suffix}`);
expect(configs).toHaveProperty(`another-config-${prefix}`); expect(configs).toHaveProperty(`another-config-${suffix}`);
}); });
const composeFileDifferentProperties = ` const composeFileDifferentProperties = `
@@ -92,25 +92,25 @@ configs:
external: true 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( const composeData = load(
composeFileDifferentProperties, composeFileDifferentProperties,
) as ComposeSpecification; ) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.configs) { if (!composeData?.configs) {
return; return;
} }
const configs = addPrefixToConfigsRoot(composeData.configs, prefix); const configs = addSuffixToConfigsRoot(composeData.configs, suffix);
expect(configs).toBeDefined(); expect(configs).toBeDefined();
for (const configKey of Object.keys(configs)) { for (const configKey of Object.keys(configs)) {
expect(configKey).toContain(`-${prefix}`); expect(configKey).toContain(`-${suffix}`);
expect(configs[configKey]).toBeDefined(); expect(configs[configKey]).toBeDefined();
} }
expect(configs).toHaveProperty(`web-config-${prefix}`); expect(configs).toHaveProperty(`web-config-${suffix}`);
expect(configs).toHaveProperty(`special-config-${prefix}`); expect(configs).toHaveProperty(`special-config-${suffix}`);
}); });
const composeFileConfigRoot = ` const composeFileConfigRoot = `
@@ -162,15 +162,15 @@ configs:
file: ./db-config.yml file: ./db-config.yml
`) as ComposeSpecification; `) 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 composeData = load(composeFileConfigRoot) as ComposeSpecification;
const prefix = "testhash"; const suffix = "testhash";
if (!composeData?.configs) { if (!composeData?.configs) {
return; return;
} }
const configs = addPrefixToConfigsRoot(composeData.configs, prefix); const configs = addSuffixToConfigsRoot(composeData.configs, suffix);
const updatedComposeData = { ...composeData, configs }; const updatedComposeData = { ...composeData, configs };
// Verificar que el resultado coincide con el archivo esperado // Verificar que el resultado coincide con el archivo esperado

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -19,19 +19,19 @@ configs:
file: ./web-config.yml 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 composeData = load(composeFile) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.services) { if (!composeData?.services) {
return; return;
} }
const services = addPrefixToConfigsInServices(composeData.services, prefix); const services = addSuffixToConfigsInServices(composeData.services, suffix);
const actualComposeData = { ...composeData, services }; const actualComposeData = { ...composeData, services };
expect(actualComposeData.services?.web?.configs).toContainEqual({ expect(actualComposeData.services?.web?.configs).toContainEqual({
source: `web-config-${prefix}`, source: `web-config-${suffix}`,
target: "/etc/nginx/nginx.conf", target: "/etc/nginx/nginx.conf",
}); });
}); });
@@ -51,17 +51,17 @@ configs:
file: ./web-config.yml 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( const composeData = load(
composeFileSingleServiceConfig, composeFileSingleServiceConfig,
) as ComposeSpecification; ) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.services) { if (!composeData?.services) {
return; return;
} }
const services = addPrefixToConfigsInServices(composeData.services, prefix); const services = addSuffixToConfigsInServices(composeData.services, suffix);
expect(services).toBeDefined(); expect(services).toBeDefined();
for (const serviceKey of Object.keys(services)) { for (const serviceKey of Object.keys(services)) {
@@ -69,7 +69,7 @@ test("Add prefix to configs in services with single config", () => {
if (serviceConfigs) { if (serviceConfigs) {
for (const config of serviceConfigs) { for (const config of serviceConfigs) {
if (typeof config === "object") { if (typeof config === "object") {
expect(config.source).toContain(`-${prefix}`); expect(config.source).toContain(`-${suffix}`);
} }
} }
} }
@@ -105,17 +105,17 @@ configs:
file: ./common-config.yml 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( const composeData = load(
composeFileMultipleServicesConfigs, composeFileMultipleServicesConfigs,
) as ComposeSpecification; ) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.services) { if (!composeData?.services) {
return; return;
} }
const services = addPrefixToConfigsInServices(composeData.services, prefix); const services = addSuffixToConfigsInServices(composeData.services, suffix);
expect(services).toBeDefined(); expect(services).toBeDefined();
for (const serviceKey of Object.keys(services)) { for (const serviceKey of Object.keys(services)) {
@@ -123,7 +123,7 @@ test("Add prefix to configs in services with multiple configs", () => {
if (serviceConfigs) { if (serviceConfigs) {
for (const config of serviceConfigs) { for (const config of serviceConfigs) {
if (typeof config === "object") { if (typeof config === "object") {
expect(config.source).toContain(`-${prefix}`); expect(config.source).toContain(`-${suffix}`);
} }
} }
} }
@@ -179,17 +179,17 @@ services:
`) as ComposeSpecification; `) as ComposeSpecification;
test("Add prefix to configs in services", () => { test("Add suffix to configs in services", () => {
const composeData = load(composeFileConfigServices) as ComposeSpecification; const composeData = load(composeFileConfigServices) as ComposeSpecification;
const prefix = "testhash"; const suffix = "testhash";
if (!composeData?.services) { if (!composeData?.services) {
return; return;
} }
const updatedComposeData = addPrefixToConfigsInServices( const updatedComposeData = addSuffixToConfigsInServices(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };

View File

@@ -1,7 +1,7 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; import { generateRandomHash } from "@/server/utils/docker/compose";
import { import {
addPrefixToAllConfigs, addSuffixToAllConfigs,
addPrefixToConfigsRoot, addSuffixToConfigsRoot,
} from "@/server/utils/docker/compose/configs"; } from "@/server/utils/docker/compose/configs";
import type { ComposeSpecification } from "@/server/utils/docker/types"; import type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
@@ -80,12 +80,12 @@ configs:
file: ./db-config.yml file: ./db-config.yml
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedComposeFileCombinedConfigs);
}); });
@@ -162,14 +162,14 @@ configs:
file: ./db-config.yml file: ./db-config.yml
`) as ComposeSpecification; `) as ComposeSpecification;
test("Add prefix to configs with environment and external", () => { test("Add suffix to configs with environment and external", () => {
const composeData = load( const composeData = load(
composeFileWithEnvAndExternal, composeFileWithEnvAndExternal,
) as ComposeSpecification; ) as ComposeSpecification;
const prefix = "testhash"; const suffix = "testhash";
const updatedComposeData = addPrefixToAllConfigs(composeData, prefix); const updatedComposeData = addSuffixToAllConfigs(composeData, suffix);
expect(updatedComposeData).toEqual(expectedComposeFileWithEnvAndExternal); expect(updatedComposeData).toEqual(expectedComposeFileWithEnvAndExternal);
}); });
@@ -234,14 +234,14 @@ configs:
file: ./db-config.yml file: ./db-config.yml
`) as ComposeSpecification; `) 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( const composeData = load(
composeFileWithTemplateDriverAndLabels, composeFileWithTemplateDriverAndLabels,
) as ComposeSpecification; ) as ComposeSpecification;
const prefix = "testhash"; const suffix = "testhash";
const updatedComposeData = addPrefixToAllConfigs(composeData, prefix); const updatedComposeData = addSuffixToAllConfigs(composeData, suffix);
expect(updatedComposeData).toEqual( expect(updatedComposeData).toEqual(
expectedComposeFileWithTemplateDriverAndLabels, expectedComposeFileWithTemplateDriverAndLabels,

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -35,19 +35,19 @@ test("Generate random hash with 8 characters", () => {
expect(hash.length).toBe(8); 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 composeData = load(composeFile) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.networks) { if (!composeData?.networks) {
return; return;
} }
const networks = addPrefixToNetworksRoot(composeData.networks, prefix); const networks = addSuffixToNetworksRoot(composeData.networks, suffix);
expect(networks).toBeDefined(); expect(networks).toBeDefined();
for (const volumeKey of Object.keys(networks)) { for (const volumeKey of Object.keys(networks)) {
expect(volumeKey).toContain(`-${prefix}`); expect(volumeKey).toContain(`-${suffix}`);
} }
}); });
@@ -79,19 +79,19 @@ networks:
internal: true 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 composeData = load(composeFile2) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.networks) { if (!composeData?.networks) {
return; return;
} }
const networks = addPrefixToNetworksRoot(composeData.networks, prefix); const networks = addSuffixToNetworksRoot(composeData.networks, suffix);
expect(networks).toBeDefined(); expect(networks).toBeDefined();
for (const networkKey of Object.keys(networks)) { for (const networkKey of Object.keys(networks)) {
expect(networkKey).toContain(`-${prefix}`); expect(networkKey).toContain(`-${suffix}`);
} }
}); });
@@ -120,19 +120,19 @@ networks:
external: true 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 composeData = load(composeFile3) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.networks) { if (!composeData?.networks) {
return; return;
} }
const networks = addPrefixToNetworksRoot(composeData.networks, prefix); const networks = addSuffixToNetworksRoot(composeData.networks, suffix);
expect(networks).toBeDefined(); expect(networks).toBeDefined();
for (const networkKey of Object.keys(networks)) { for (const networkKey of Object.keys(networks)) {
expect(networkKey).toContain(`-${prefix}`); expect(networkKey).toContain(`-${suffix}`);
} }
}); });
@@ -160,19 +160,19 @@ networks:
external: true 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 composeData = load(composeFile4) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.networks) { if (!composeData?.networks) {
return; return;
} }
const networks = addPrefixToNetworksRoot(composeData.networks, prefix); const networks = addSuffixToNetworksRoot(composeData.networks, suffix);
expect(networks).toBeDefined(); expect(networks).toBeDefined();
for (const networkKey of Object.keys(networks)) { for (const networkKey of Object.keys(networks)) {
expect(networkKey).toContain(`-${prefix}`); expect(networkKey).toContain(`-${suffix}`);
} }
}); });
@@ -201,19 +201,19 @@ networks:
external: true 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 composeData = load(composeFile5) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.networks) { if (!composeData?.networks) {
return; return;
} }
const networks = addPrefixToNetworksRoot(composeData.networks, prefix); const networks = addSuffixToNetworksRoot(composeData.networks, suffix);
expect(networks).toBeDefined(); expect(networks).toBeDefined();
for (const networkKey of Object.keys(networks)) { for (const networkKey of Object.keys(networks)) {
expect(networkKey).toContain(`-${prefix}`); expect(networkKey).toContain(`-${suffix}`);
} }
}); });
@@ -240,7 +240,7 @@ networks:
external: true external: true
`; `;
// Expected compose file with static prefix `testhash` // Expected compose file with static suffix `testhash`
const expectedComposeFile6 = ` const expectedComposeFile6 = `
version: "3.8" version: "3.8"
@@ -264,18 +264,70 @@ networks:
external: true 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 composeData = load(composeFile6) as ComposeSpecification;
const prefix = "testhash"; const suffix = "testhash";
if (!composeData?.networks) { if (!composeData?.networks) {
return; return;
} }
const networks = addPrefixToNetworksRoot(composeData.networks, prefix); const networks = addSuffixToNetworksRoot(composeData.networks, suffix);
const expectedComposeData = load( const expectedComposeData = load(
expectedComposeFile6, expectedComposeFile6,
) as ComposeSpecification; ) as ComposeSpecification;
expect(networks).toStrictEqual(expectedComposeData.networks); 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 suffix to dokploy-network", () => {
const composeData = load(composeFile7) as ComposeSpecification;
const suffix = generateRandomHash();
if (!composeData?.networks) {
return;
}
const networks = addSuffixToNetworksRoot(composeData.networks, suffix);
expect(networks).toBeDefined();
for (const networkKey of Object.keys(networks)) {
expect(networkKey).toContain("dokploy-network");
}
});

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -20,30 +20,30 @@ services:
- backend - backend
`; `;
test("Add prefix to networks in services", () => { test("Add suffix to networks in services", () => {
const composeData = load(composeFile) as ComposeSpecification; const composeData = load(composeFile) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.services) { if (!composeData?.services) {
return; return;
} }
const services = addPrefixToServiceNetworks(composeData.services, prefix); const services = addSuffixToServiceNetworks(composeData.services, suffix);
const actualComposeData = { ...composeData, services }; const actualComposeData = { ...composeData, services };
expect(actualComposeData?.services?.web?.networks).toContain( expect(actualComposeData?.services?.web?.networks).toContain(
`frontend-${prefix}`, `frontend-${suffix}`,
); );
expect(actualComposeData?.services?.api?.networks).toContain( expect(actualComposeData?.services?.api?.networks).toContain(
`backend-${prefix}`, `backend-${suffix}`,
); );
const apiNetworks = actualComposeData?.services?.api?.networks; const apiNetworks = actualComposeData?.services?.api?.networks;
expect(apiNetworks).toBeDefined(); expect(apiNetworks).toBeDefined();
expect(actualComposeData?.services?.api?.networks).toContain( expect(actualComposeData?.services?.api?.networks).toContain(
`backend-${prefix}`, `backend-${suffix}`,
); );
}); });
@@ -64,26 +64,26 @@ networks:
driver: bridge 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 composeData = load(composeFile2) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.services) { if (!composeData?.services) {
return; return;
} }
const services = addPrefixToServiceNetworks(composeData.services, prefix); const services = addSuffixToServiceNetworks(composeData.services, suffix);
const actualComposeData = { ...composeData, services }; const actualComposeData = { ...composeData, services };
expect(actualComposeData.services?.api?.networks).toHaveProperty( expect(actualComposeData.services?.api?.networks).toHaveProperty(
`frontend-${prefix}`, `frontend-${suffix}`,
); );
const networkConfig = actualComposeData?.services?.api?.networks as { const networkConfig = actualComposeData?.services?.api?.networks as {
[key: string]: { aliases?: string[] }; [key: string]: { aliases?: string[] };
}; };
expect(networkConfig[`frontend-${prefix}`]).toBeDefined(); expect(networkConfig[`frontend-${suffix}`]).toBeDefined();
expect(networkConfig[`frontend-${prefix}`]?.aliases).toContain("api"); expect(networkConfig[`frontend-${suffix}`]?.aliases).toContain("api");
expect(actualComposeData.services?.api?.networks).not.toHaveProperty( expect(actualComposeData.services?.api?.networks).not.toHaveProperty(
"frontend-ash", "frontend-ash",
@@ -104,19 +104,19 @@ networks:
driver: bridge 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 composeData = load(composeFile3) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.services) { if (!composeData?.services) {
return; return;
} }
const services = addPrefixToServiceNetworks(composeData.services, prefix); const services = addSuffixToServiceNetworks(composeData.services, suffix);
const actualComposeData = { ...composeData, services }; const actualComposeData = { ...composeData, services };
expect(actualComposeData.services?.redis?.networks).toHaveProperty( expect(actualComposeData.services?.redis?.networks).toHaveProperty(
`backend-${prefix}`, `backend-${suffix}`,
); );
}); });
@@ -150,35 +150,124 @@ networks:
driver: bridge 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 composeData = load(composeFileCombined) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.services) { if (!composeData?.services) {
return; return;
} }
const services = addPrefixToServiceNetworks(composeData.services, prefix); const services = addSuffixToServiceNetworks(composeData.services, suffix);
const actualComposeData = { ...composeData, services }; const actualComposeData = { ...composeData, services };
// Caso 1: ListOfStrings // Caso 1: ListOfStrings
expect(actualComposeData.services?.web?.networks).toContain( expect(actualComposeData.services?.web?.networks).toContain(
`frontend-${prefix}`, `frontend-${suffix}`,
); );
expect(actualComposeData.services?.web?.networks).toContain( expect(actualComposeData.services?.web?.networks).toContain(
`backend-${prefix}`, `backend-${suffix}`,
); );
// Caso 2: Objeto con aliases // Caso 2: Objeto con aliases
const apiNetworks = actualComposeData.services?.api?.networks as { const apiNetworks = actualComposeData.services?.api?.networks as {
[key: string]: unknown; [key: string]: unknown;
}; };
expect(apiNetworks).toHaveProperty(`frontend-${prefix}`); expect(apiNetworks).toHaveProperty(`frontend-${suffix}`);
expect(apiNetworks[`frontend-${prefix}`]).toBeDefined(); expect(apiNetworks[`frontend-${suffix}`]).toBeDefined();
expect(apiNetworks).not.toHaveProperty("frontend"); expect(apiNetworks).not.toHaveProperty("frontend");
// Caso 3: Objeto con redes simples // Caso 3: Objeto con redes simples
const redisNetworks = actualComposeData.services?.redis?.networks; const redisNetworks = actualComposeData.services?.redis?.networks;
expect(redisNetworks).toHaveProperty(`backend-${prefix}`); expect(redisNetworks).toHaveProperty(`backend-${suffix}`);
expect(redisNetworks).not.toHaveProperty("backend"); expect(redisNetworks).not.toHaveProperty("backend");
}); });
const composeFile7 = `
version: "3.8"
services:
web:
image: nginx:latest
networks:
- dokploy-network
`;
test("It shoudn't add suffix to dokploy-network in services", () => {
const composeData = load(composeFile7) as ComposeSpecification;
const suffix = generateRandomHash();
if (!composeData?.services) {
return;
}
const networks = addSuffixToServiceNetworks(composeData.services, suffix);
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 suffix to dokploy-network in services multiples cases", () => {
const composeData = load(composeFile8) as ComposeSpecification;
const suffix = generateRandomHash();
if (!composeData?.services) {
return;
}
const networks = addSuffixToServiceNetworks(composeData.services, suffix);
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();
});

View File

@@ -1,9 +1,9 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; import { generateRandomHash } from "@/server/utils/docker/compose";
import { import {
addPrefixToAllNetworks, addSuffixToAllNetworks,
addPrefixToServiceNetworks, addSuffixToServiceNetworks,
} from "@/server/utils/docker/compose/network"; } 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -38,54 +38,54 @@ networks:
driver: bridge 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 composeData = load(composeFileCombined) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
// Prefijo para redes definidas en el root // Prefijo para redes definidas en el root
if (composeData.networks) { if (composeData.networks) {
composeData.networks = addPrefixToNetworksRoot( composeData.networks = addSuffixToNetworksRoot(
composeData.networks, composeData.networks,
prefix, suffix,
); );
} }
// Prefijo para redes definidas en los servicios // Prefijo para redes definidas en los servicios
if (composeData.services) { if (composeData.services) {
composeData.services = addPrefixToServiceNetworks( composeData.services = addSuffixToServiceNetworks(
composeData.services, composeData.services,
prefix, suffix,
); );
} }
const actualComposeData = { ...composeData }; const actualComposeData = { ...composeData };
// Verificar redes en root // Verificar redes en root
expect(actualComposeData.networks).toHaveProperty(`frontend-${prefix}`); expect(actualComposeData.networks).toHaveProperty(`frontend-${suffix}`);
expect(actualComposeData.networks).toHaveProperty(`backend-${prefix}`); expect(actualComposeData.networks).toHaveProperty(`backend-${suffix}`);
expect(actualComposeData.networks).not.toHaveProperty("frontend"); expect(actualComposeData.networks).not.toHaveProperty("frontend");
expect(actualComposeData.networks).not.toHaveProperty("backend"); expect(actualComposeData.networks).not.toHaveProperty("backend");
// Caso 1: ListOfStrings // Caso 1: ListOfStrings
expect(actualComposeData.services?.web?.networks).toContain( expect(actualComposeData.services?.web?.networks).toContain(
`frontend-${prefix}`, `frontend-${suffix}`,
); );
expect(actualComposeData.services?.web?.networks).toContain( expect(actualComposeData.services?.web?.networks).toContain(
`backend-${prefix}`, `backend-${suffix}`,
); );
// Caso 2: Objeto con aliases // Caso 2: Objeto con aliases
const apiNetworks = actualComposeData.services?.api?.networks as { const apiNetworks = actualComposeData.services?.api?.networks as {
[key: string]: { aliases?: string[] }; [key: string]: { aliases?: string[] };
}; };
expect(apiNetworks).toHaveProperty(`frontend-${prefix}`); expect(apiNetworks).toHaveProperty(`frontend-${suffix}`);
expect(apiNetworks?.[`frontend-${prefix}`]?.aliases).toContain("api"); expect(apiNetworks?.[`frontend-${suffix}`]?.aliases).toContain("api");
expect(apiNetworks).not.toHaveProperty("frontend"); expect(apiNetworks).not.toHaveProperty("frontend");
// Caso 3: Objeto con redes simples // Caso 3: Objeto con redes simples
const redisNetworks = actualComposeData.services?.redis?.networks; const redisNetworks = actualComposeData.services?.redis?.networks;
expect(redisNetworks).toHaveProperty(`backend-${prefix}`); expect(redisNetworks).toHaveProperty(`backend-${suffix}`);
expect(redisNetworks).not.toHaveProperty("backend"); expect(redisNetworks).not.toHaveProperty("backend");
}); });
@@ -119,14 +119,14 @@ networks:
driver: bridge 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 composeData = load(composeFileCombined) as ComposeSpecification;
const prefix = "testhash"; const suffix = "testhash";
if (!composeData?.networks) { if (!composeData?.networks) {
return; return;
} }
const updatedComposeData = addPrefixToAllNetworks(composeData, prefix); const updatedComposeData = addSuffixToAllNetworks(composeData, suffix);
expect(updatedComposeData).toEqual(expectedComposeFile); expect(updatedComposeData).toEqual(expectedComposeFile);
}); });
@@ -181,11 +181,11 @@ networks:
driver: bridge 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 composeData = load(composeFile2) as ComposeSpecification;
const prefix = "testhash"; const suffix = "testhash";
const updatedComposeData = addPrefixToAllNetworks(composeData, prefix); const updatedComposeData = addSuffixToAllNetworks(composeData, suffix);
expect(updatedComposeData).toEqual(expectedComposeFile2); expect(updatedComposeData).toEqual(expectedComposeFile2);
}); });
@@ -246,11 +246,90 @@ networks:
com.docker.network.bridge.enable_icc: "true" 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 composeData = load(composeFile3) as ComposeSpecification;
const prefix = "testhash"; const suffix = "testhash";
const updatedComposeData = addPrefixToAllNetworks(composeData, prefix); const updatedComposeData = addSuffixToAllNetworks(composeData, suffix);
expect(updatedComposeData).toEqual(expectedComposeFile3); 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 suffix to dokploy-network in compose file with multiple services and complex network configurations", () => {
const composeData = load(composeFile4) as ComposeSpecification;
const suffix = "testhash";
const updatedComposeData = addSuffixToAllNetworks(composeData, suffix);
console.log(updatedComposeData);
expect(updatedComposeData).toEqual(expectedComposeFile4);
});

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { dump, load } from "js-yaml"; import { dump, load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -23,18 +23,18 @@ secrets:
file: ./db_password.txt 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 composeData = load(composeFileSecretsRoot) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.secrets) { if (!composeData?.secrets) {
return; return;
} }
const secrets = addPrefixToSecretsRoot(composeData.secrets, prefix); const secrets = addSuffixToSecretsRoot(composeData.secrets, suffix);
expect(secrets).toBeDefined(); expect(secrets).toBeDefined();
if (secrets) { if (secrets) {
for (const secretKey of Object.keys(secrets)) { for (const secretKey of Object.keys(secrets)) {
expect(secretKey).toContain(`-${prefix}`); expect(secretKey).toContain(`-${suffix}`);
expect(secrets[secretKey]).toBeDefined(); expect(secrets[secretKey]).toBeDefined();
} }
} }
@@ -52,19 +52,19 @@ secrets:
file: ./api_key.txt 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 composeData = load(composeFileSecretsRoot1) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.secrets) { if (!composeData?.secrets) {
return; return;
} }
const secrets = addPrefixToSecretsRoot(composeData.secrets, prefix); const secrets = addSuffixToSecretsRoot(composeData.secrets, suffix);
expect(secrets).toBeDefined(); expect(secrets).toBeDefined();
if (secrets) { if (secrets) {
for (const secretKey of Object.keys(secrets)) { for (const secretKey of Object.keys(secrets)) {
expect(secretKey).toContain(`-${prefix}`); expect(secretKey).toContain(`-${suffix}`);
expect(secrets[secretKey]).toBeDefined(); expect(secrets[secretKey]).toBeDefined();
} }
} }
@@ -84,19 +84,19 @@ secrets:
external: true 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 composeData = load(composeFileSecretsRoot2) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.secrets) { if (!composeData?.secrets) {
return; return;
} }
const secrets = addPrefixToSecretsRoot(composeData.secrets, prefix); const secrets = addSuffixToSecretsRoot(composeData.secrets, suffix);
expect(secrets).toBeDefined(); expect(secrets).toBeDefined();
if (secrets) { if (secrets) {
for (const secretKey of Object.keys(secrets)) { for (const secretKey of Object.keys(secrets)) {
expect(secretKey).toContain(`-${prefix}`); expect(secretKey).toContain(`-${suffix}`);
expect(secrets[secretKey]).toBeDefined(); expect(secrets[secretKey]).toBeDefined();
} }
} }

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -18,22 +18,22 @@ secrets:
file: ./db_password.txt 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 composeData = load(composeFileSecretsServices) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToSecretsInServices( const updatedComposeData = addSuffixToSecretsInServices(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
expect(actualComposeData.services?.db?.secrets).toContain( expect(actualComposeData.services?.db?.secrets).toContain(
`db_password-${prefix}`, `db_password-${suffix}`,
); );
}); });
@@ -51,22 +51,22 @@ secrets:
file: ./app_secret.txt 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 composeData = load(composeFileSecretsServices1) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToSecretsInServices( const updatedComposeData = addSuffixToSecretsInServices(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
expect(actualComposeData.services?.app?.secrets).toContain( expect(actualComposeData.services?.app?.secrets).toContain(
`app_secret-${prefix}`, `app_secret-${suffix}`,
); );
}); });
@@ -90,24 +90,24 @@ secrets:
file: ./frontend_secret.txt 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 composeData = load(composeFileSecretsServices2) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToSecretsInServices( const updatedComposeData = addSuffixToSecretsInServices(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
expect(actualComposeData.services?.backend?.secrets).toContain( expect(actualComposeData.services?.backend?.secrets).toContain(
`backend_secret-${prefix}`, `backend_secret-${suffix}`,
); );
expect(actualComposeData.services?.frontend?.secrets).toContain( expect(actualComposeData.services?.frontend?.secrets).toContain(
`frontend_secret-${prefix}`, `frontend_secret-${suffix}`,
); );
}); });

View File

@@ -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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -47,11 +47,11 @@ secrets:
file: ./app_secret.txt file: ./app_secret.txt
`) as ComposeSpecification; `) as ComposeSpecification;
test("Add prefix to all secrets", () => { test("Add suffix to all secrets", () => {
const composeData = load(composeFileCombinedSecrets) as ComposeSpecification; 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); expect(updatedComposeData).toEqual(expectedComposeFileCombinedSecrets);
}); });
@@ -98,11 +98,11 @@ secrets:
file: ./cache_secret.txt file: ./cache_secret.txt
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedComposeFileCombinedSecrets3);
}); });
@@ -149,11 +149,11 @@ secrets:
file: ./db_password.txt file: ./db_password.txt
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedComposeFileCombinedSecrets4);
}); });

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -27,33 +27,33 @@ test("Generate random hash with 8 characters", () => {
expect(hash.length).toBe(8); 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 composeData = load(composeFile) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToServiceNames( const updatedComposeData = addSuffixToServiceNames(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
// Verificar que el nombre del contenedor ha cambiado correctamente // Verificar que el nombre del contenedor ha cambiado correctamente
expect(actualComposeData.services?.[`web-${prefix}`]?.container_name).toBe( expect(actualComposeData.services?.[`web-${suffix}`]?.container_name).toBe(
`web_container-${prefix}`, `web_container-${suffix}`,
); );
// Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe // 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"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // 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", "nginx:latest",
); );
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
}); });

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -32,49 +32,49 @@ networks:
driver: bridge 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 composeData = load(composeFile4) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToServiceNames( const updatedComposeData = addSuffixToServiceNames(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
// Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe // 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"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // 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", "nginx:latest",
); );
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que los nombres en depends_on tienen el prefijo // Verificar que los nombres en depends_on tienen el prefijo
expect(actualComposeData.services?.[`web-${prefix}`]?.depends_on).toContain( expect(actualComposeData.services?.[`web-${suffix}`]?.depends_on).toContain(
`db-${prefix}`, `db-${suffix}`,
); );
expect(actualComposeData.services?.[`web-${prefix}`]?.depends_on).toContain( expect(actualComposeData.services?.[`web-${suffix}`]?.depends_on).toContain(
`api-${prefix}`, `api-${suffix}`,
); );
// Verificar que los servicios `db` y `api` también tienen el prefijo // 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).not.toHaveProperty("db");
expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`db-${suffix}`]?.image).toBe(
"postgres:latest", "postgres:latest",
); );
expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); expect(actualComposeData.services).toHaveProperty(`api-${suffix}`);
expect(actualComposeData.services).not.toHaveProperty("api"); expect(actualComposeData.services).not.toHaveProperty("api");
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
}); });
@@ -102,49 +102,49 @@ networks:
driver: bridge 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 composeData = load(composeFile5) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToServiceNames( const updatedComposeData = addSuffixToServiceNames(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
// Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe // 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"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // 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", "nginx:latest",
); );
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que los nombres en depends_on tienen el prefijo // 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<string, any>; ?.depends_on as Record<string, any>;
expect(webDependsOn).toHaveProperty(`db-${prefix}`); expect(webDependsOn).toHaveProperty(`db-${suffix}`);
expect(webDependsOn).toHaveProperty(`api-${prefix}`); expect(webDependsOn).toHaveProperty(`api-${suffix}`);
expect(webDependsOn[`db-${prefix}`].condition).toBe("service_healthy"); expect(webDependsOn[`db-${suffix}`].condition).toBe("service_healthy");
expect(webDependsOn[`api-${prefix}`].condition).toBe("service_started"); expect(webDependsOn[`api-${suffix}`].condition).toBe("service_started");
// Verificar que los servicios `db` y `api` también tienen el prefijo // 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).not.toHaveProperty("db");
expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`db-${suffix}`]?.image).toBe(
"postgres:latest", "postgres:latest",
); );
expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); expect(actualComposeData.services).toHaveProperty(`api-${suffix}`);
expect(actualComposeData.services).not.toHaveProperty("api"); expect(actualComposeData.services).not.toHaveProperty("api");
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
}); });

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -30,41 +30,41 @@ networks:
driver: bridge 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 composeData = load(composeFile6) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToServiceNames( const updatedComposeData = addSuffixToServiceNames(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
// Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe // 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"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // 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", "nginx:latest",
); );
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que el nombre en extends tiene el prefijo // Verificar que el nombre en extends tiene el prefijo
expect(actualComposeData.services?.[`web-${prefix}`]?.extends).toBe( expect(actualComposeData.services?.[`web-${suffix}`]?.extends).toBe(
`base_service-${prefix}`, `base_service-${suffix}`,
); );
// Verificar que el servicio `base_service` también tiene el prefijo // 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).not.toHaveProperty("base_service");
expect(actualComposeData.services?.[`base_service-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`base_service-${suffix}`]?.image).toBe(
"base:latest", "base:latest",
); );
}); });
@@ -90,42 +90,42 @@ networks:
driver: bridge 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 composeData = load(composeFile7) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToServiceNames( const updatedComposeData = addSuffixToServiceNames(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
// Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe // 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"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // 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", "nginx:latest",
); );
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que el nombre en extends.service tiene el prefijo // 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") { 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 // 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).not.toHaveProperty("base_service");
expect(actualComposeData.services?.[`base_service-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`base_service-${suffix}`]?.image).toBe(
"base:latest", "base:latest",
); );
}); });

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -31,46 +31,46 @@ networks:
driver: bridge 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 composeData = load(composeFile2) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToServiceNames( const updatedComposeData = addSuffixToServiceNames(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
// Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe // 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"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // 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", "nginx:latest",
); );
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que los nombres en links tienen el prefijo // Verificar que los nombres en links tienen el prefijo
expect(actualComposeData.services?.[`web-${prefix}`]?.links).toContain( expect(actualComposeData.services?.[`web-${suffix}`]?.links).toContain(
`db-${prefix}`, `db-${suffix}`,
); );
// Verificar que los servicios `db` y `api` también tienen el prefijo // 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).not.toHaveProperty("db");
expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`db-${suffix}`]?.image).toBe(
"postgres:latest", "postgres:latest",
); );
expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); expect(actualComposeData.services).toHaveProperty(`api-${suffix}`);
expect(actualComposeData.services).not.toHaveProperty("api"); expect(actualComposeData.services).not.toHaveProperty("api");
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
}); });

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -26,23 +26,23 @@ networks:
driver: bridge 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 composeData = load(composeFile) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToServiceNames( const updatedComposeData = addSuffixToServiceNames(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
// Verificar que los nombres de los servicios han cambiado correctamente // Verificar que los nombres de los servicios han cambiado correctamente
expect(actualComposeData.services).toHaveProperty(`web-${prefix}`); expect(actualComposeData.services).toHaveProperty(`web-${suffix}`);
expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); expect(actualComposeData.services).toHaveProperty(`api-${suffix}`);
// Verificar que las claves originales no existen // Verificar que las claves originales no existen
expect(actualComposeData.services).not.toHaveProperty("web"); expect(actualComposeData.services).not.toHaveProperty("web");
expect(actualComposeData.services).not.toHaveProperty("api"); expect(actualComposeData.services).not.toHaveProperty("api");

View File

@@ -1,6 +1,6 @@
import { import {
addPrefixToAllServiceNames, addSuffixToAllServiceNames,
addPrefixToServiceNames, addSuffixToServiceNames,
} from "@/server/utils/docker/compose/service"; } from "@/server/utils/docker/compose/service";
import type { ComposeSpecification } from "@/server/utils/docker/types"; import type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
@@ -70,17 +70,17 @@ networks:
driver: bridge 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 composeData = load(composeFileCombinedAllCases) as ComposeSpecification;
const prefix = "testhash"; const suffix = "testhash";
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToServiceNames( const updatedComposeData = addSuffixToServiceNames(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
@@ -175,11 +175,11 @@ networks:
driver: bridge driver: bridge
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedComposeFile1);
}); });
@@ -270,11 +270,11 @@ networks:
driver: bridge driver: bridge
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedComposeFile2);
}); });
@@ -365,11 +365,11 @@ networks:
driver: bridge driver: bridge
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedComposeFile3);
}); });

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -35,44 +35,44 @@ networks:
driver: bridge 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 composeData = load(composeFile3) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToServiceNames( const updatedComposeData = addSuffixToServiceNames(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
// Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe // 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"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // 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", "nginx:latest",
); );
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`api-${suffix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que los nombres en volumes_from tienen el prefijo // Verificar que los nombres en volumes_from tienen el prefijo
expect(actualComposeData.services?.[`web-${prefix}`]?.volumes_from).toContain( expect(actualComposeData.services?.[`web-${suffix}`]?.volumes_from).toContain(
`shared-${prefix}`, `shared-${suffix}`,
); );
expect(actualComposeData.services?.[`api-${prefix}`]?.volumes_from).toContain( expect(actualComposeData.services?.[`api-${suffix}`]?.volumes_from).toContain(
`shared-${prefix}`, `shared-${suffix}`,
); );
// Verificar que el servicio shared también tiene el prefijo // 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).not.toHaveProperty("shared");
expect(actualComposeData.services?.[`shared-${prefix}`]?.image).toBe( expect(actualComposeData.services?.[`shared-${suffix}`]?.image).toBe(
"busybox", "busybox",
); );
}); });

View File

@@ -1,7 +1,7 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; import { generateRandomHash } from "@/server/utils/docker/compose";
import { import {
addPrefixToAllVolumes, addSuffixToAllVolumes,
addPrefixToVolumesRoot, addSuffixToVolumesRoot,
} from "@/server/utils/docker/compose/volume"; } from "@/server/utils/docker/compose/volume";
import type { ComposeSpecification } from "@/server/utils/docker/types"; import type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; 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 // 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 // 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 composeData = load(composeFile) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.volumes) { if (!composeData?.volumes) {
return; return;
} }
const volumes = addPrefixToVolumesRoot(composeData.volumes, prefix); const volumes = addSuffixToVolumesRoot(composeData.volumes, suffix);
// { // {
// 'db-data-af045046': { driver: 'local' }, // 'db-data-af045046': { driver: 'local' },
@@ -160,15 +160,15 @@ test("Add prefix to volumes root property", () => {
expect(volumes).toBeDefined(); expect(volumes).toBeDefined();
for (const volumeKey of Object.keys(volumes)) { 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 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); expect(updatedComposeData).toEqual(expectedDockerCompose);
}); });
@@ -217,11 +217,11 @@ volumes:
mongo-data-testhash: mongo-data-testhash:
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedDockerCompose2);
}); });
@@ -270,11 +270,11 @@ volumes:
mongo-data-testhash: mongo-data-testhash:
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedDockerCompose3);
}); });
@@ -1011,11 +1011,11 @@ volumes:
db-config-testhash: db-config-testhash:
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedDockerComposeComplex);
}); });
@@ -1110,11 +1110,11 @@ volumes:
db-data-testhash: db-data-testhash:
`) as ComposeSpecification; `) 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 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); expect(updatedComposeData).toEqual(expectedDockerComposeExample1);
}); });

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -29,18 +29,18 @@ test("Generate random hash with 8 characters", () => {
expect(hash.length).toBe(8); 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 composeData = load(composeFile) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.volumes) { if (!composeData?.volumes) {
return; return;
} }
const volumes = addPrefixToVolumesRoot(composeData.volumes, prefix); const volumes = addSuffixToVolumesRoot(composeData.volumes, suffix);
expect(volumes).toBeDefined(); expect(volumes).toBeDefined();
for (const volumeKey of Object.keys(volumes)) { for (const volumeKey of Object.keys(volumes)) {
expect(volumeKey).toContain(`-${prefix}`); expect(volumeKey).toContain(`-${suffix}`);
expect(volumes[volumeKey]).toBeDefined(); expect(volumes[volumeKey]).toBeDefined();
} }
}); });
@@ -67,18 +67,18 @@ networks:
driver: bridge 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 composeData = load(composeFile2) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.volumes) { if (!composeData?.volumes) {
return; return;
} }
const volumes = addPrefixToVolumesRoot(composeData.volumes, prefix); const volumes = addSuffixToVolumesRoot(composeData.volumes, suffix);
expect(volumes).toBeDefined(); expect(volumes).toBeDefined();
for (const volumeKey of Object.keys(volumes)) { for (const volumeKey of Object.keys(volumes)) {
expect(volumeKey).toContain(`-${prefix}`); expect(volumeKey).toContain(`-${suffix}`);
expect(volumes[volumeKey]).toBeDefined(); expect(volumes[volumeKey]).toBeDefined();
} }
}); });
@@ -101,19 +101,19 @@ networks:
driver: bridge 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 composeData = load(composeFile3) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData?.volumes) { if (!composeData?.volumes) {
return; return;
} }
const volumes = addPrefixToVolumesRoot(composeData.volumes, prefix); const volumes = addSuffixToVolumesRoot(composeData.volumes, suffix);
expect(volumes).toBeDefined(); expect(volumes).toBeDefined();
for (const volumeKey of Object.keys(volumes)) { for (const volumeKey of Object.keys(volumes)) {
expect(volumeKey).toContain(`-${prefix}`); expect(volumeKey).toContain(`-${suffix}`);
expect(volumes[volumeKey]).toBeDefined(); expect(volumes[volumeKey]).toBeDefined();
} }
}); });
@@ -179,15 +179,15 @@ volumes:
`) as ComposeSpecification; `) 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 composeData = load(composeFile4) as ComposeSpecification;
const prefix = "testhash"; const suffix = "testhash";
if (!composeData?.volumes) { if (!composeData?.volumes) {
return; return;
} }
const volumes = addPrefixToVolumesRoot(composeData.volumes, prefix); const volumes = addSuffixToVolumesRoot(composeData.volumes, suffix);
const updatedComposeData = { ...composeData, volumes }; const updatedComposeData = { ...composeData, volumes };
// Verificar que el resultado coincide con el archivo esperado // Verificar que el resultado coincide con el archivo esperado

View File

@@ -1,5 +1,5 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; 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 type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { expect, test } from "vitest"; import { expect, test } from "vitest";
@@ -21,22 +21,22 @@ services:
- db_data:/var/lib/postgresql/data - 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 composeData = load(composeFile1) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToVolumesInServices( const updatedComposeData = addSuffixToVolumesInServices(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
expect(actualComposeData.services?.db?.volumes).toContain( 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 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 composeData = load(composeFileTypeVolume) as ComposeSpecification;
const prefix = generateRandomHash(); const suffix = generateRandomHash();
if (!composeData.services) { if (!composeData.services) {
return; return;
} }
const updatedComposeData = addPrefixToVolumesInServices( const updatedComposeData = addSuffixToVolumesInServices(
composeData.services, composeData.services,
prefix, suffix,
); );
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
expect(actualComposeData.services?.db?.volumes).toEqual([ expect(actualComposeData.services?.db?.volumes).toEqual([
{ {
type: "volume", type: "volume",
source: `db-test-${prefix}`, source: `db-test-${suffix}`,
target: "/var/lib/postgresql/data", target: "/var/lib/postgresql/data",
}, },
]); ]);

View File

@@ -1,7 +1,7 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; import { generateRandomHash } from "@/server/utils/docker/compose";
import { import {
addPrefixToAllVolumes, addSuffixToAllVolumes,
addPrefixToVolumesInServices, addSuffixToVolumesInServices,
} from "@/server/utils/docker/compose/volume"; } from "@/server/utils/docker/compose/volume";
import type { ComposeSpecification } from "@/server/utils/docker/types"; import type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
@@ -47,12 +47,12 @@ volumes:
driver: local driver: local
`) as ComposeSpecification; `) 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 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 }; const actualComposeData = { ...composeData, ...updatedComposeData };
expect(actualComposeData).toEqual(expectedComposeFileTypeVolume); expect(actualComposeData).toEqual(expectedComposeFileTypeVolume);
@@ -96,12 +96,12 @@ volumes:
driver: local driver: local
`) as ComposeSpecification; `) 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 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 }; const actualComposeData = { ...composeData, ...updatedComposeData };
expect(actualComposeData).toEqual(expectedComposeFileTypeVolume1); expect(actualComposeData).toEqual(expectedComposeFileTypeVolume1);
@@ -157,12 +157,12 @@ volumes:
device: /path/to/app/logs device: /path/to/app/logs
`) as ComposeSpecification; `) 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 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 }; const actualComposeData = { ...composeData, ...updatedComposeData };
expect(actualComposeData).toEqual(expectedComposeFileTypeVolume2); expect(actualComposeData).toEqual(expectedComposeFileTypeVolume2);
@@ -276,12 +276,12 @@ volumes:
device: /path/to/shared/logs device: /path/to/shared/logs
`) as ComposeSpecification; `) 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 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 }; const actualComposeData = { ...composeData, ...updatedComposeData };
expect(actualComposeData).toEqual(expectedComposeFileTypeVolume3); expect(actualComposeData).toEqual(expectedComposeFileTypeVolume3);

View File

@@ -161,7 +161,7 @@ export const AddDomain = ({
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel>Host</FormLabel> <FormLabel>Host</FormLabel>
<div className="flex max-lg:flex-wrap sm:flex-row gap-2"> <div className="flex gap-2">
<FormControl> <FormControl>
<Input placeholder="api.dokploy.com" {...field} /> <Input placeholder="api.dokploy.com" {...field} />
</FormControl> </FormControl>

View File

@@ -197,7 +197,7 @@ export const AddDomainCompose = ({
render={({ field }) => ( render={({ field }) => (
<FormItem className="w-full"> <FormItem className="w-full">
<FormLabel>Service Name</FormLabel> <FormLabel>Service Name</FormLabel>
<div className="flex max-lg:flex-wrap sm:flex-row gap-2"> <div className="flex gap-2">
<Select <Select
onValueChange={field.onChange} onValueChange={field.onChange}
defaultValue={field.value || ""} defaultValue={field.value || ""}
@@ -297,7 +297,7 @@ export const AddDomainCompose = ({
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel>Host</FormLabel> <FormLabel>Host</FormLabel>
<div className="flex max-lg:flex-wrap sm:flex-row gap-2"> <div className="flex gap-2">
<FormControl> <FormControl>
<Input placeholder="api.dokploy.com" {...field} /> <Input placeholder="api.dokploy.com" {...field} />
</FormControl> </FormControl>

View File

@@ -83,9 +83,10 @@ export const ComposeFileEditor = ({ composeId }: Props) => {
}; };
return ( return (
<> <>
<div className="w-full flex flex-col lg:flex-row gap-4 "> <div className="w-full flex flex-col gap-4 ">
<Form {...form}> <Form {...form}>
<form <form
id="hook-form-save-compose-file"
onSubmit={form.handleSubmit(onSubmit)} onSubmit={form.handleSubmit(onSubmit)}
className="w-full relative space-y-4" className="w-full relative space-y-4"
> >
@@ -121,21 +122,21 @@ services:
</FormItem> </FormItem>
)} )}
/> />
<div className="flex justify-between flex-col lg:flex-row gap-2">
<div className="w-full flex flex-col lg:flex-row gap-4 items-end">
<RandomizeCompose composeId={composeId} />
</div>
<Button
type="submit"
isLoading={isLoading}
className="lg:w-fit w-full"
>
Save
</Button>
</div>
</form> </form>
</Form> </Form>
<div className="flex justify-between flex-col lg:flex-row gap-2">
<div className="w-full flex flex-col lg:flex-row gap-4 items-end">
<RandomizeCompose composeId={composeId} />
</div>
<Button
type="submit"
form="hook-form-save-compose-file"
isLoading={isLoading}
className="lg:w-fit w-full"
>
Save
</Button>
</div>
</div> </div>
</> </>
); );

View File

@@ -1,5 +1,7 @@
import { AlertBlock } from "@/components/shared/alert-block"; import { AlertBlock } from "@/components/shared/alert-block";
import { CodeEditor } from "@/components/shared/code-editor";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { CardTitle } from "@/components/ui/card";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -8,28 +10,94 @@ import {
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input"; 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 { api } from "@/utils/api";
import { Dices } from "lucide-react"; import { zodResolver } from "@hookform/resolvers/zod";
import { useState } from "react"; import { AlertTriangle, Dices } from "lucide-react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod";
interface Props { interface Props {
composeId: string; composeId: string;
} }
const schema = z.object({
suffix: z.string(),
randomize: z.boolean().optional(),
});
type Schema = z.infer<typeof schema>;
export const RandomizeCompose = ({ composeId }: Props) => { export const RandomizeCompose = ({ composeId }: Props) => {
const utils = api.useUtils(); const utils = api.useUtils();
const [prefix, setPrefix] = useState<string>("");
const [compose, setCompose] = useState<string>(""); const [compose, setCompose] = useState<string>("");
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const { mutateAsync, error, isError } = const { mutateAsync, error, isError } =
api.compose.randomizeCompose.useMutation(); 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<Schema>({
defaultValues: {
suffix: "",
randomize: false,
},
resolver: zodResolver(schema),
});
const suffix = form.watch("suffix");
useEffect(() => {
if (data) {
form.reset({
suffix: data?.suffix || "",
randomize: data?.randomize || false,
});
}
}, [form, form.reset, form.formState.isSubmitSuccessful, data]);
const onSubmit = async (formData: Schema) => {
await updateCompose({
composeId,
suffix: formData?.suffix || "",
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({ await mutateAsync({
composeId, composeId,
prefix, suffix,
}) })
.then(async (data) => { .then(async (data) => {
await utils.project.all.invalidate(); await utils.project.all.invalidate();
@@ -43,7 +111,7 @@ export const RandomizeCompose = ({ composeId }: Props) => {
return ( return (
<Dialog open={isOpen} onOpenChange={setIsOpen}> <Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild onClick={() => onSubmit()}> <DialogTrigger asChild onClick={() => randomizeCompose()}>
<Button className="max-lg:w-full" variant="outline"> <Button className="max-lg:w-full" variant="outline">
<Dices className="h-4 w-4" /> <Dices className="h-4 w-4" />
Randomize Compose Randomize Compose
@@ -59,7 +127,7 @@ export const RandomizeCompose = ({ composeId }: Props) => {
</DialogHeader> </DialogHeader>
<div className="text-sm text-muted-foreground flex flex-col gap-2"> <div className="text-sm text-muted-foreground flex flex-col gap-2">
<span> <span>
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 property to avoid conflicts
</span> </span>
<ul className="list-disc list-inside"> <ul className="list-disc list-inside">
@@ -69,29 +137,98 @@ export const RandomizeCompose = ({ composeId }: Props) => {
<li>configs</li> <li>configs</li>
<li>secrets</li> <li>secrets</li>
</ul> </ul>
</div> <AlertBlock type="info">
<div className="flex flex-col lg:flex-row gap-2"> When you activate this option, we will include a env
<Input `COMPOSE_PREFIX` variable to the compose file so you can use it in
placeholder="Enter a prefix (Optional, example: prod)" your compose file.
onChange={(e) => setPrefix(e.target.value)} </AlertBlock>
/>
<Button
type="submit"
onClick={async () => {
await onSubmit();
}}
className="lg:w-fit w-full"
>
Random
</Button>
</div> </div>
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>} {isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
id="hook-form-add-project"
className="grid w-full gap-4"
>
{isError && (
<div className="flex flex-row gap-4 rounded-lg items-center bg-red-50 p-2 dark:bg-red-950">
<AlertTriangle className="text-red-600 dark:text-red-400" />
<span className="text-sm text-red-600 dark:text-red-400">
{error?.message}
</span>
</div>
)}
<div className="p-4 bg-secondary rounded-lg"> <div className="flex flex-col lg:flex-col gap-4 w-full ">
<pre> <div>
<code className="language-yaml">{compose}</code> <FormField
</pre> control={form.control}
</div> name="suffix"
render={({ field }) => (
<FormItem className="flex flex-col justify-center max-sm:items-center w-full">
<FormLabel>Suffix</FormLabel>
<FormControl>
<Input
placeholder="Enter a suffix (Optional, example: prod)"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="randomize"
render={({ field }) => (
<FormItem className="mt-4 flex flex-row items-center justify-between rounded-lg border p-3 shadow-sm">
<div className="space-y-0.5">
<FormLabel>Apply Randomize</FormLabel>
<FormDescription>
Apply randomize to the compose file.
</FormDescription>
</div>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
</div>
<div className="flex flex-col lg:flex-row gap-4 w-full items-end justify-end">
<Button
form="hook-form-add-project"
type="submit"
className="lg:w-fit"
>
Save
</Button>
<Button
type="button"
variant="secondary"
onClick={async () => {
await randomizeCompose();
}}
className="lg:w-fit"
>
Random
</Button>
</div>
</div>
<pre>
<CodeEditor
value={compose || ""}
language="yaml"
readOnly
height="50rem"
/>
</pre>
</form>
</Form>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); );

View File

@@ -0,0 +1,2 @@
ALTER TABLE "compose" ADD COLUMN "suffix" text DEFAULT '' NOT NULL;--> statement-breakpoint
ALTER TABLE "compose" ADD COLUMN "randomize" boolean DEFAULT false NOT NULL;

File diff suppressed because it is too large Load Diff

View File

@@ -246,6 +246,13 @@
"when": 1725256397019, "when": 1725256397019,
"tag": "0034_aspiring_secret_warriors", "tag": "0034_aspiring_secret_warriors",
"breakpoints": true "breakpoints": true
},
{
"idx": 35,
"version": "6",
"when": 1725429324584,
"tag": "0035_cool_gravity",
"breakpoints": true
} }
] ]
} }

View File

@@ -15,7 +15,10 @@ import {
} from "@/server/queues/deployments-queue"; } from "@/server/queues/deployments-queue";
import { myQueue } from "@/server/queues/queueSetup"; import { myQueue } from "@/server/queues/queueSetup";
import { createCommand } from "@/server/utils/builders/compose"; 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 { addDomainToCompose, cloneCompose } from "@/server/utils/docker/domain";
import { removeComposeDirectory } from "@/server/utils/filesystem/directory"; import { removeComposeDirectory } from "@/server/utils/filesystem/directory";
import { templates } from "@/templates/templates"; import { templates } from "@/templates/templates";
@@ -141,7 +144,7 @@ export const composeRouter = createTRPCRouter({
randomizeCompose: protectedProcedure randomizeCompose: protectedProcedure
.input(apiRandomizeCompose) .input(apiRandomizeCompose)
.mutation(async ({ input }) => { .mutation(async ({ input }) => {
return await randomizeComposeFile(input.composeId, input.prefix); return await randomizeComposeFile(input.composeId, input.suffix);
}), }),
getConvertedCompose: protectedProcedure getConvertedCompose: protectedProcedure
.input(apiFindCompose) .input(apiFindCompose)
@@ -150,6 +153,7 @@ export const composeRouter = createTRPCRouter({
const domains = await findDomainsByComposeId(input.composeId); const domains = await findDomainsByComposeId(input.composeId);
const composeFile = await addDomainToCompose(compose, domains); const composeFile = await addDomainToCompose(compose, domains);
return dump(composeFile, { return dump(composeFile, {
lineWidth: 1000, lineWidth: 1000,
}); });

View File

@@ -4,6 +4,7 @@ import { db } from "@/server/db";
import { type apiCreateCompose, compose } from "@/server/db/schema"; import { type apiCreateCompose, compose } from "@/server/db/schema";
import { generateAppName } from "@/server/db/schema/utils"; import { generateAppName } from "@/server/db/schema/utils";
import { buildCompose } from "@/server/utils/builders/compose"; import { buildCompose } from "@/server/utils/builders/compose";
import { randomizeSpecificationFile } from "@/server/utils/docker/compose";
import { cloneCompose, loadDockerCompose } from "@/server/utils/docker/domain"; import { cloneCompose, loadDockerCompose } from "@/server/utils/docker/domain";
import { sendBuildErrorNotifications } from "@/server/utils/notifications/build-error"; import { sendBuildErrorNotifications } from "@/server/utils/notifications/build-error";
import { sendBuildSuccessNotifications } from "@/server/utils/notifications/build-success"; import { sendBuildSuccessNotifications } from "@/server/utils/notifications/build-success";
@@ -117,7 +118,16 @@ export const loadServices = async (
await cloneCompose(compose); await cloneCompose(compose);
} }
const composeData = await loadDockerCompose(compose); let composeData = await loadDockerCompose(compose);
if (compose.randomize && composeData) {
const randomizedCompose = randomizeSpecificationFile(
composeData,
compose.suffix,
);
composeData = randomizedCompose;
}
if (!composeData?.services) { if (!composeData?.services) {
throw new TRPCError({ throw new TRPCError({
code: "NOT_FOUND", code: "NOT_FOUND",

View File

@@ -64,6 +64,8 @@ export const compose = pgTable("compose", {
command: text("command").notNull().default(""), command: text("command").notNull().default(""),
// //
composePath: text("composePath").notNull().default("./docker-compose.yml"), composePath: text("composePath").notNull().default("./docker-compose.yml"),
suffix: text("suffix").notNull().default(""),
randomize: boolean("randomize").notNull().default(false),
composeStatus: applicationStatus("composeStatus").notNull().default("idle"), composeStatus: applicationStatus("composeStatus").notNull().default("idle"),
projectId: text("projectId") projectId: text("projectId")
.notNull() .notNull()
@@ -157,6 +159,6 @@ export const apiRandomizeCompose = createSchema
composeId: true, composeId: true,
}) })
.extend({ .extend({
prefix: z.string().optional(), suffix: z.string().optional(),
composeId: z.string().min(1), composeId: z.string().min(1),
}); });

View File

@@ -109,6 +109,10 @@ const createEnvFile = (compose: ComposeNested) => {
envContent += "\nDOCKER_CONFIG=/root/.docker/config.json"; envContent += "\nDOCKER_CONFIG=/root/.docker/config.json";
} }
if (compose.randomize) {
envContent += `\nCOMPOSE_PREFIX=${compose.suffix}`;
}
const envFileContent = prepareEnvironmentVariables(envContent).join("\n"); const envFileContent = prepareEnvironmentVariables(envContent).join("\n");
if (!existsSync(dirname(envFilePath))) { if (!existsSync(dirname(envFilePath))) {

View File

@@ -1,11 +1,11 @@
import crypto from "node:crypto"; import crypto from "node:crypto";
import { findComposeById } from "@/server/api/services/compose"; import { findComposeById } from "@/server/api/services/compose";
import { dump, load } from "js-yaml"; import { dump, load } from "js-yaml";
import { addPrefixToAllConfigs } from "./compose/configs"; import { addSuffixToAllConfigs } from "./compose/configs";
import { addPrefixToAllNetworks } from "./compose/network"; import { addSuffixToAllNetworks } from "./compose/network";
import { addPrefixToAllSecrets } from "./compose/secrets"; import { addSuffixToAllSecrets } from "./compose/secrets";
import { addPrefixToAllServiceNames } from "./compose/service"; import { addSuffixToAllServiceNames } from "./compose/service";
import { addPrefixToAllVolumes } from "./compose/volume"; import { addSuffixToAllVolumes } from "./compose/volume";
import type { ComposeSpecification } from "./types"; import type { ComposeSpecification } from "./types";
export const generateRandomHash = (): string => { export const generateRandomHash = (): string => {
@@ -14,32 +14,43 @@ export const generateRandomHash = (): string => {
export const randomizeComposeFile = async ( export const randomizeComposeFile = async (
composeId: string, composeId: string,
prefix?: string, suffix?: string,
) => { ) => {
const compose = await findComposeById(composeId); const compose = await findComposeById(composeId);
const composeFile = compose.composeFile; const composeFile = compose.composeFile;
const composeData = load(composeFile) as ComposeSpecification; 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); return dump(newComposeFile);
}; };
export const addPrefixToAllProperties = ( export const randomizeSpecificationFile = (
composeSpec: ComposeSpecification,
suffix?: string,
) => {
if (!suffix) {
return composeSpec;
}
const newComposeFile = addSuffixToAllProperties(composeSpec, suffix);
return newComposeFile;
};
export const addSuffixToAllProperties = (
composeData: ComposeSpecification, composeData: ComposeSpecification,
prefix: string, suffix: string,
): ComposeSpecification => { ): ComposeSpecification => {
let updatedComposeData = { ...composeData }; let updatedComposeData = { ...composeData };
updatedComposeData = addPrefixToAllServiceNames(updatedComposeData, prefix); updatedComposeData = addSuffixToAllServiceNames(updatedComposeData, suffix);
updatedComposeData = addPrefixToAllVolumes(updatedComposeData, prefix); updatedComposeData = addSuffixToAllVolumes(updatedComposeData, suffix);
updatedComposeData = addPrefixToAllNetworks(updatedComposeData, prefix); updatedComposeData = addSuffixToAllNetworks(updatedComposeData, suffix);
updatedComposeData = addPrefixToAllConfigs(updatedComposeData, prefix); updatedComposeData = addSuffixToAllConfigs(updatedComposeData, suffix);
updatedComposeData = addPrefixToAllSecrets(updatedComposeData, prefix); updatedComposeData = addSuffixToAllSecrets(updatedComposeData, suffix);
return updatedComposeData; return updatedComposeData;
}; };

View File

@@ -5,23 +5,23 @@ import type {
DefinitionsService, DefinitionsService,
} from "../types"; } from "../types";
export const addPrefixToConfigsRoot = ( export const addSuffixToConfigsRoot = (
configs: { [key: string]: DefinitionsConfig }, configs: { [key: string]: DefinitionsConfig },
prefix: string, suffix: string,
): { [key: string]: DefinitionsConfig } => { ): { [key: string]: DefinitionsConfig } => {
const newConfigs: { [key: string]: DefinitionsConfig } = {}; const newConfigs: { [key: string]: DefinitionsConfig } = {};
_.forEach(configs, (config, configName) => { _.forEach(configs, (config, configName) => {
const newConfigName = `${configName}-${prefix}`; const newConfigName = `${configName}-${suffix}`;
newConfigs[newConfigName] = _.cloneDeep(config); newConfigs[newConfigName] = _.cloneDeep(config);
}); });
return newConfigs; return newConfigs;
}; };
export const addPrefixToConfigsInServices = ( export const addSuffixToConfigsInServices = (
services: { [key: string]: DefinitionsService }, services: { [key: string]: DefinitionsService },
prefix: string, suffix: string,
): { [key: string]: DefinitionsService } => { ): { [key: string]: DefinitionsService } => {
const newServices: { [key: string]: DefinitionsService } = {}; const newServices: { [key: string]: DefinitionsService } = {};
@@ -32,12 +32,12 @@ export const addPrefixToConfigsInServices = (
if (_.has(newServiceConfig, "configs")) { if (_.has(newServiceConfig, "configs")) {
newServiceConfig.configs = _.map(newServiceConfig.configs, (config) => { newServiceConfig.configs = _.map(newServiceConfig.configs, (config) => {
if (_.isString(config)) { if (_.isString(config)) {
return `${config}-${prefix}`; return `${config}-${suffix}`;
} }
if (_.isObject(config) && config.source) { if (_.isObject(config) && config.source) {
return { return {
...config, ...config,
source: `${config.source}-${prefix}`, source: `${config.source}-${suffix}`,
}; };
} }
return config; return config;
@@ -50,22 +50,22 @@ export const addPrefixToConfigsInServices = (
return newServices; return newServices;
}; };
export const addPrefixToAllConfigs = ( export const addSuffixToAllConfigs = (
composeData: ComposeSpecification, composeData: ComposeSpecification,
prefix: string, suffix: string,
): ComposeSpecification => { ): ComposeSpecification => {
const updatedComposeData = { ...composeData }; const updatedComposeData = { ...composeData };
if (composeData?.configs) { if (composeData?.configs) {
updatedComposeData.configs = addPrefixToConfigsRoot( updatedComposeData.configs = addSuffixToConfigsRoot(
composeData.configs, composeData.configs,
prefix, suffix,
); );
} }
if (composeData?.services) { if (composeData?.services) {
updatedComposeData.services = addPrefixToConfigsInServices( updatedComposeData.services = addSuffixToConfigsInServices(
composeData.services, composeData.services,
prefix, suffix,
); );
} }

View File

@@ -5,30 +5,40 @@ import type {
DefinitionsService, DefinitionsService,
} from "../types"; } from "../types";
export const addPrefixToNetworksRoot = ( export const addSuffixToNetworksRoot = (
networks: { [key: string]: DefinitionsNetwork }, networks: { [key: string]: DefinitionsNetwork },
prefix: string, suffix: string,
): { [key: string]: DefinitionsNetwork } => { ): { [key: string]: DefinitionsNetwork } => {
return _.mapKeys(networks, (_value, key) => `${key}-${prefix}`); return _.mapKeys(networks, (_value, key) => {
if (key === "dokploy-network") {
return "dokploy-network";
}
return `${key}-${suffix}`;
});
}; };
export const addPrefixToServiceNetworks = ( export const addSuffixToServiceNetworks = (
services: { [key: string]: DefinitionsService }, services: { [key: string]: DefinitionsService },
prefix: string, suffix: string,
): { [key: string]: DefinitionsService } => { ): { [key: string]: DefinitionsService } => {
return _.mapValues(services, (service) => { return _.mapValues(services, (service) => {
if (service.networks) { if (service.networks) {
// 1 Case the most common // 1 Case the most common
if (Array.isArray(service.networks)) { if (Array.isArray(service.networks)) {
service.networks = service.networks.map( service.networks = service.networks.map((network: string) => {
(network: string) => `${network}-${prefix}`, if (network === "dokploy-network") {
); return "dokploy-network";
}
return `${network}-${suffix}`;
});
} else { } else {
// 2 Case // 2 Case
service.networks = _.mapKeys( service.networks = _.mapKeys(service.networks, (_value, key) => {
service.networks, if (key === "dokploy-network") {
(_value, key) => `${key}-${prefix}`, return "dokploy-network";
); }
return `${key}-${suffix}`;
});
// 3 Case // 3 Case
service.networks = _.mapValues(service.networks, (value) => { service.networks = _.mapValues(service.networks, (value) => {
@@ -37,9 +47,10 @@ export const addPrefixToServiceNetworks = (
if (innerKey === "aliases") { if (innerKey === "aliases") {
return "aliases"; return "aliases";
} }
return `${innerKey}-${prefix}`; return `${innerKey}-${suffix}`;
}); });
} }
return value; return value;
}); });
} }
@@ -48,23 +59,23 @@ export const addPrefixToServiceNetworks = (
}); });
}; };
export const addPrefixToAllNetworks = ( export const addSuffixToAllNetworks = (
composeData: ComposeSpecification, composeData: ComposeSpecification,
prefix: string, suffix: string,
): ComposeSpecification => { ): ComposeSpecification => {
const updatedComposeData = { ...composeData }; const updatedComposeData = { ...composeData };
if (updatedComposeData.networks) { if (updatedComposeData.networks) {
updatedComposeData.networks = addPrefixToNetworksRoot( updatedComposeData.networks = addSuffixToNetworksRoot(
updatedComposeData.networks, updatedComposeData.networks,
prefix, suffix,
); );
} }
if (updatedComposeData.services) { if (updatedComposeData.services) {
updatedComposeData.services = addPrefixToServiceNetworks( updatedComposeData.services = addSuffixToServiceNetworks(
updatedComposeData.services, updatedComposeData.services,
prefix, suffix,
); );
} }

View File

@@ -1,21 +1,21 @@
import _ from "lodash"; import _ from "lodash";
import type { ComposeSpecification, DefinitionsService } from "../types"; import type { ComposeSpecification, DefinitionsService } from "../types";
export const addPrefixToSecretsRoot = ( export const addSuffixToSecretsRoot = (
secrets: ComposeSpecification["secrets"], secrets: ComposeSpecification["secrets"],
prefix: string, suffix: string,
): ComposeSpecification["secrets"] => { ): ComposeSpecification["secrets"] => {
const newSecrets: ComposeSpecification["secrets"] = {}; const newSecrets: ComposeSpecification["secrets"] = {};
_.forEach(secrets, (secretConfig, secretName) => { _.forEach(secrets, (secretConfig, secretName) => {
const newSecretName = `${secretName}-${prefix}`; const newSecretName = `${secretName}-${suffix}`;
newSecrets[newSecretName] = _.cloneDeep(secretConfig); newSecrets[newSecretName] = _.cloneDeep(secretConfig);
}); });
return newSecrets; return newSecrets;
}; };
export const addPrefixToSecretsInServices = ( export const addSuffixToSecretsInServices = (
services: { [key: string]: DefinitionsService }, services: { [key: string]: DefinitionsService },
prefix: string, suffix: string,
): { [key: string]: DefinitionsService } => { ): { [key: string]: DefinitionsService } => {
const newServices: { [key: string]: DefinitionsService } = {}; const newServices: { [key: string]: DefinitionsService } = {};
@@ -26,12 +26,12 @@ export const addPrefixToSecretsInServices = (
if (_.has(newServiceConfig, "secrets")) { if (_.has(newServiceConfig, "secrets")) {
newServiceConfig.secrets = _.map(newServiceConfig.secrets, (secret) => { newServiceConfig.secrets = _.map(newServiceConfig.secrets, (secret) => {
if (_.isString(secret)) { if (_.isString(secret)) {
return `${secret}-${prefix}`; return `${secret}-${suffix}`;
} }
if (_.isObject(secret) && secret.source) { if (_.isObject(secret) && secret.source) {
return { return {
...secret, ...secret,
source: `${secret.source}-${prefix}`, source: `${secret.source}-${suffix}`,
}; };
} }
return secret; return secret;
@@ -44,23 +44,23 @@ export const addPrefixToSecretsInServices = (
return newServices; return newServices;
}; };
export const addPrefixToAllSecrets = ( export const addSuffixToAllSecrets = (
composeData: ComposeSpecification, composeData: ComposeSpecification,
prefix: string, suffix: string,
): ComposeSpecification => { ): ComposeSpecification => {
const updatedComposeData = { ...composeData }; const updatedComposeData = { ...composeData };
if (composeData?.secrets) { if (composeData?.secrets) {
updatedComposeData.secrets = addPrefixToSecretsRoot( updatedComposeData.secrets = addSuffixToSecretsRoot(
composeData.secrets, composeData.secrets,
prefix, suffix,
); );
} }
if (composeData?.services) { if (composeData?.services) {
updatedComposeData.services = addPrefixToSecretsInServices( updatedComposeData.services = addSuffixToSecretsInServices(
composeData.services, composeData.services,
prefix, suffix,
); );
} }

View File

@@ -12,28 +12,28 @@ type DependsOnObject = NonNullable<
: never : never
>; >;
export const addPrefixToServiceNames = ( export const addSuffixToServiceNames = (
services: { [key: string]: DefinitionsService }, services: { [key: string]: DefinitionsService },
prefix: string, suffix: string,
): { [key: string]: DefinitionsService } => { ): { [key: string]: DefinitionsService } => {
const newServices: { [key: string]: DefinitionsService } = {}; const newServices: { [key: string]: DefinitionsService } = {};
for (const [serviceName, serviceConfig] of Object.entries(services)) { for (const [serviceName, serviceConfig] of Object.entries(services)) {
const newServiceName = `${serviceName}-${prefix}`; const newServiceName = `${serviceName}-${suffix}`;
const newServiceConfig = _.cloneDeep(serviceConfig); const newServiceConfig = _.cloneDeep(serviceConfig);
// Reemplazar nombres de servicios en depends_on // Reemplazar nombres de servicios en depends_on
if (newServiceConfig.depends_on) { if (newServiceConfig.depends_on) {
if (Array.isArray(newServiceConfig.depends_on)) { if (Array.isArray(newServiceConfig.depends_on)) {
newServiceConfig.depends_on = newServiceConfig.depends_on.map( newServiceConfig.depends_on = newServiceConfig.depends_on.map(
(dep) => `${dep}-${prefix}`, (dep) => `${dep}-${suffix}`,
); );
} else { } else {
const newDependsOn: DependsOnObject = {}; const newDependsOn: DependsOnObject = {};
for (const [depName, depConfig] of Object.entries( for (const [depName, depConfig] of Object.entries(
newServiceConfig.depends_on, newServiceConfig.depends_on,
)) { )) {
newDependsOn[`${depName}-${prefix}`] = depConfig; newDependsOn[`${depName}-${suffix}`] = depConfig;
} }
newServiceConfig.depends_on = newDependsOn; newServiceConfig.depends_on = newDependsOn;
} }
@@ -41,29 +41,29 @@ export const addPrefixToServiceNames = (
// Reemplazar nombre en container_name // Reemplazar nombre en container_name
if (newServiceConfig.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 // Reemplazar nombres de servicios en links
if (newServiceConfig.links) { if (newServiceConfig.links) {
newServiceConfig.links = newServiceConfig.links.map( newServiceConfig.links = newServiceConfig.links.map(
(link) => `${link}-${prefix}`, (link) => `${link}-${suffix}`,
); );
} }
// Reemplazar nombres de servicios en extends // Reemplazar nombres de servicios en extends
if (newServiceConfig.extends) { if (newServiceConfig.extends) {
if (typeof newServiceConfig.extends === "string") { if (typeof newServiceConfig.extends === "string") {
newServiceConfig.extends = `${newServiceConfig.extends}-${prefix}`; newServiceConfig.extends = `${newServiceConfig.extends}-${suffix}`;
} else { } else {
newServiceConfig.extends.service = `${newServiceConfig.extends.service}-${prefix}`; newServiceConfig.extends.service = `${newServiceConfig.extends.service}-${suffix}`;
} }
} }
// Reemplazar nombres de servicios en volumes_from // Reemplazar nombres de servicios en volumes_from
if (newServiceConfig.volumes_from) { if (newServiceConfig.volumes_from) {
newServiceConfig.volumes_from = newServiceConfig.volumes_from.map( newServiceConfig.volumes_from = newServiceConfig.volumes_from.map(
(vol) => `${vol}-${prefix}`, (vol) => `${vol}-${suffix}`,
); );
} }
@@ -73,16 +73,16 @@ export const addPrefixToServiceNames = (
return newServices; return newServices;
}; };
export const addPrefixToAllServiceNames = ( export const addSuffixToAllServiceNames = (
composeData: ComposeSpecification, composeData: ComposeSpecification,
prefix: string, suffix: string,
): ComposeSpecification => { ): ComposeSpecification => {
const updatedComposeData = { ...composeData }; const updatedComposeData = { ...composeData };
if (updatedComposeData.services) { if (updatedComposeData.services) {
updatedComposeData.services = addPrefixToServiceNames( updatedComposeData.services = addSuffixToServiceNames(
updatedComposeData.services, updatedComposeData.services,
prefix, suffix,
); );
} }

View File

@@ -6,16 +6,16 @@ import type {
} from "../types"; } from "../types";
// Función para agregar prefijo a volúmenes // Función para agregar prefijo a volúmenes
export const addPrefixToVolumesRoot = ( export const addSuffixToVolumesRoot = (
volumes: { [key: string]: DefinitionsVolume }, volumes: { [key: string]: DefinitionsVolume },
prefix: string, suffix: string,
): { [key: string]: DefinitionsVolume } => { ): { [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 }, services: { [key: string]: DefinitionsService },
prefix: string, suffix: string,
): { [key: string]: DefinitionsService } => { ): { [key: string]: DefinitionsService } => {
const newServices: { [key: string]: DefinitionsService } = {}; const newServices: { [key: string]: DefinitionsService } = {};
@@ -36,12 +36,12 @@ export const addPrefixToVolumesInServices = (
) { ) {
return volume; return volume;
} }
return `${volumeName}-${prefix}:${path}`; return `${volumeName}-${suffix}:${path}`;
} }
if (_.isObject(volume) && volume.type === "volume" && volume.source) { if (_.isObject(volume) && volume.type === "volume" && volume.source) {
return { return {
...volume, ...volume,
source: `${volume.source}-${prefix}`, source: `${volume.source}-${suffix}`,
}; };
} }
return volume; return volume;
@@ -54,23 +54,23 @@ export const addPrefixToVolumesInServices = (
return newServices; return newServices;
}; };
export const addPrefixToAllVolumes = ( export const addSuffixToAllVolumes = (
composeData: ComposeSpecification, composeData: ComposeSpecification,
prefix: string, suffix: string,
): ComposeSpecification => { ): ComposeSpecification => {
const updatedComposeData = { ...composeData }; const updatedComposeData = { ...composeData };
if (updatedComposeData.volumes) { if (updatedComposeData.volumes) {
updatedComposeData.volumes = addPrefixToVolumesRoot( updatedComposeData.volumes = addSuffixToVolumesRoot(
updatedComposeData.volumes, updatedComposeData.volumes,
prefix, suffix,
); );
} }
if (updatedComposeData.services) { if (updatedComposeData.services) {
updatedComposeData.services = addPrefixToVolumesInServices( updatedComposeData.services = addSuffixToVolumesInServices(
updatedComposeData.services, updatedComposeData.services,
prefix, suffix,
); );
} }

View File

@@ -10,6 +10,7 @@ import { cloneGitRawRepository } from "../providers/git";
import { cloneRawGithubRepository } from "../providers/github"; import { cloneRawGithubRepository } from "../providers/github";
import { cloneRawGitlabRepository } from "../providers/gitlab"; import { cloneRawGitlabRepository } from "../providers/gitlab";
import { createComposeFileRaw } from "../providers/raw"; import { createComposeFileRaw } from "../providers/raw";
import { randomizeSpecificationFile } from "./compose";
import type { import type {
ComposeSpecification, ComposeSpecification,
DefinitionsService, DefinitionsService,
@@ -72,7 +73,12 @@ export const writeDomainsToCompose = async (
if (!domains.length) { if (!domains.length) {
return; return;
} }
const composeConverted = await addDomainToCompose(compose, domains); let composeConverted = await addDomainToCompose(compose, domains);
if (compose.randomize && composeConverted) {
const result = randomizeSpecificationFile(composeConverted, compose.suffix);
composeConverted = result;
}
const path = getComposePath(compose); const path = getComposePath(compose);
const composeString = dump(composeConverted, { lineWidth: 1000 }); const composeString = dump(composeConverted, { lineWidth: 1000 });
@@ -88,12 +94,17 @@ export const addDomainToCompose = async (
domains: Domain[], domains: Domain[],
) => { ) => {
const { appName } = compose; const { appName } = compose;
const result = await loadDockerCompose(compose); let result = await loadDockerCompose(compose);
if (!result || domains.length === 0) { if (!result || domains.length === 0) {
return null; return null;
} }
if (compose.randomize) {
const randomized = randomizeSpecificationFile(result, compose.suffix);
result = randomized;
}
for (const domain of domains) { for (const domain of domains) {
const { serviceName, https } = domain; const { serviceName, https } = domain;
if (!serviceName) { if (!serviceName) {