mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Merge branch 'canary' of github.com:Dokploy/dokploy into feat/condition-certificate
This commit is contained in:
187
__test__/traefik/traefik.test.ts
Normal file
187
__test__/traefik/traefik.test.ts
Normal file
@@ -0,0 +1,187 @@
|
||||
import type { Domain } from "@/server/api/services/domain";
|
||||
import type { Redirect } from "@/server/api/services/redirect";
|
||||
import type { ApplicationNested } from "@/server/utils/builders";
|
||||
import { createRouterConfig } from "@/server/utils/traefik/domain";
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
const baseApp: ApplicationNested = {
|
||||
applicationId: "",
|
||||
applicationStatus: "done",
|
||||
appName: "",
|
||||
autoDeploy: true,
|
||||
branch: null,
|
||||
buildArgs: null,
|
||||
buildPath: "/",
|
||||
buildType: "nixpacks",
|
||||
command: null,
|
||||
cpuLimit: null,
|
||||
cpuReservation: null,
|
||||
createdAt: "",
|
||||
customGitBranch: "",
|
||||
customGitBuildPath: "",
|
||||
customGitSSHKey: "",
|
||||
customGitUrl: "",
|
||||
description: "",
|
||||
dockerfile: null,
|
||||
dockerImage: null,
|
||||
dropBuildPath: null,
|
||||
enabled: null,
|
||||
env: null,
|
||||
healthCheckSwarm: null,
|
||||
labelsSwarm: null,
|
||||
memoryLimit: null,
|
||||
memoryReservation: null,
|
||||
modeSwarm: null,
|
||||
mounts: [],
|
||||
name: "",
|
||||
networkSwarm: null,
|
||||
owner: null,
|
||||
password: null,
|
||||
placementSwarm: null,
|
||||
ports: [],
|
||||
projectId: "",
|
||||
redirects: [],
|
||||
refreshToken: "",
|
||||
registry: null,
|
||||
registryId: null,
|
||||
replicas: 1,
|
||||
repository: null,
|
||||
restartPolicySwarm: null,
|
||||
rollbackConfigSwarm: null,
|
||||
security: [],
|
||||
sourceType: "git",
|
||||
subtitle: null,
|
||||
title: null,
|
||||
updateConfigSwarm: null,
|
||||
username: null,
|
||||
};
|
||||
|
||||
const baseDomain: Domain = {
|
||||
applicationId: "",
|
||||
certificateType: "none",
|
||||
createdAt: "",
|
||||
domainId: "",
|
||||
host: "",
|
||||
https: false,
|
||||
path: null,
|
||||
port: null,
|
||||
uniqueConfigKey: 1,
|
||||
};
|
||||
|
||||
const baseRedirect: Redirect = {
|
||||
redirectId: "",
|
||||
regex: "",
|
||||
replacement: "",
|
||||
permanent: false,
|
||||
uniqueConfigKey: 1,
|
||||
createdAt: "",
|
||||
applicationId: "",
|
||||
};
|
||||
|
||||
/** Middlewares */
|
||||
|
||||
test("Web entrypoint on http domain", async () => {
|
||||
const router = await createRouterConfig(
|
||||
baseApp,
|
||||
{ ...baseDomain, https: false },
|
||||
"web",
|
||||
);
|
||||
|
||||
expect(router.middlewares).not.toContain("redirect-to-https");
|
||||
});
|
||||
|
||||
test("Web entrypoint on http domain with redirect", async () => {
|
||||
const router = await createRouterConfig(
|
||||
{
|
||||
...baseApp,
|
||||
appName: "test",
|
||||
redirects: [{ ...baseRedirect, uniqueConfigKey: 1 }],
|
||||
},
|
||||
{ ...baseDomain, https: false },
|
||||
"web",
|
||||
);
|
||||
|
||||
expect(router.middlewares).not.toContain("redirect-to-https");
|
||||
expect(router.middlewares).toContain("redirect-test-1");
|
||||
});
|
||||
|
||||
test("Web entrypoint on http domain with multiple redirect", async () => {
|
||||
const router = await createRouterConfig(
|
||||
{
|
||||
...baseApp,
|
||||
appName: "test",
|
||||
redirects: [
|
||||
{ ...baseRedirect, uniqueConfigKey: 1 },
|
||||
{ ...baseRedirect, uniqueConfigKey: 2 },
|
||||
],
|
||||
},
|
||||
{ ...baseDomain, https: false },
|
||||
"web",
|
||||
);
|
||||
|
||||
expect(router.middlewares).not.toContain("redirect-to-https");
|
||||
expect(router.middlewares).toContain("redirect-test-1");
|
||||
expect(router.middlewares).toContain("redirect-test-2");
|
||||
});
|
||||
|
||||
test("Web entrypoint on https domain", async () => {
|
||||
const router = await createRouterConfig(
|
||||
baseApp,
|
||||
{ ...baseDomain, https: true },
|
||||
"web",
|
||||
);
|
||||
|
||||
expect(router.middlewares).toContain("redirect-to-https");
|
||||
});
|
||||
|
||||
test("Web entrypoint on https domain with redirect", async () => {
|
||||
const router = await createRouterConfig(
|
||||
{
|
||||
...baseApp,
|
||||
appName: "test",
|
||||
redirects: [{ ...baseRedirect, uniqueConfigKey: 1 }],
|
||||
},
|
||||
{ ...baseDomain, https: true },
|
||||
"web",
|
||||
);
|
||||
|
||||
expect(router.middlewares).toContain("redirect-to-https");
|
||||
expect(router.middlewares).not.toContain("redirect-test-1");
|
||||
});
|
||||
|
||||
test("Websecure entrypoint on https domain", async () => {
|
||||
const router = await createRouterConfig(
|
||||
baseApp,
|
||||
{ ...baseDomain, https: true },
|
||||
"websecure",
|
||||
);
|
||||
|
||||
expect(router.middlewares).not.toContain("redirect-to-https");
|
||||
});
|
||||
|
||||
test("Websecure entrypoint on https domain with redirect", async () => {
|
||||
const router = await createRouterConfig(
|
||||
{
|
||||
...baseApp,
|
||||
appName: "test",
|
||||
redirects: [{ ...baseRedirect, uniqueConfigKey: 1 }],
|
||||
},
|
||||
{ ...baseDomain, https: true },
|
||||
"websecure",
|
||||
);
|
||||
|
||||
expect(router.middlewares).not.toContain("redirect-to-https");
|
||||
expect(router.middlewares).toContain("redirect-test-1");
|
||||
});
|
||||
|
||||
/** Certificates */
|
||||
|
||||
test("CertificateType on websecure entrypoint", async () => {
|
||||
const router = await createRouterConfig(
|
||||
baseApp,
|
||||
{ ...baseDomain, certificateType: "letsencrypt" },
|
||||
"websecure",
|
||||
);
|
||||
|
||||
expect(router.tls?.certResolver).toBe("letsencrypt");
|
||||
});
|
||||
@@ -13,12 +13,27 @@ export const manageDomain = async (app: ApplicationNested, domain: Domain) => {
|
||||
const config: FileConfig = loadOrCreateConfig(appName);
|
||||
const serviceName = `${appName}-service-${domain.uniqueConfigKey}`;
|
||||
const routerName = `${appName}-router-${domain.uniqueConfigKey}`;
|
||||
const routerNameSecure = `${appName}-router-websecure-${domain.uniqueConfigKey}`;
|
||||
|
||||
config.http = config.http || { routers: {}, services: {} };
|
||||
config.http.routers = config.http.routers || {};
|
||||
config.http.services = config.http.services || {};
|
||||
|
||||
config.http.routers[routerName] = await createRouterConfig(app, domain);
|
||||
config.http.routers[routerName] = await createRouterConfig(
|
||||
app,
|
||||
domain,
|
||||
"web",
|
||||
);
|
||||
|
||||
if (domain.https) {
|
||||
config.http.routers[routerNameSecure] = await createRouterConfig(
|
||||
app,
|
||||
domain,
|
||||
"websecure",
|
||||
);
|
||||
} else {
|
||||
delete config.http.routers[routerNameSecure];
|
||||
}
|
||||
|
||||
config.http.services[serviceName] = createServiceConfig(appName, domain);
|
||||
writeTraefikConfig(config, appName);
|
||||
@@ -28,10 +43,15 @@ export const removeDomain = async (appName: string, uniqueKey: number) => {
|
||||
const config: FileConfig = loadOrCreateConfig(appName);
|
||||
|
||||
const routerKey = `${appName}-router-${uniqueKey}`;
|
||||
const routerSecureKey = `${appName}-router-websecure-${uniqueKey}`;
|
||||
|
||||
const serviceKey = `${appName}-service-${uniqueKey}`;
|
||||
if (config.http?.routers?.[routerKey]) {
|
||||
delete config.http.routers[routerKey];
|
||||
}
|
||||
if (config.http?.routers?.[routerSecureKey]) {
|
||||
delete config.http.routers[routerSecureKey];
|
||||
}
|
||||
if (config.http?.services?.[serviceKey]) {
|
||||
delete config.http.services[serviceKey];
|
||||
}
|
||||
@@ -47,7 +67,11 @@ export const removeDomain = async (appName: string, uniqueKey: number) => {
|
||||
}
|
||||
};
|
||||
|
||||
const createRouterConfig = async (app: ApplicationNested, domain: Domain) => {
|
||||
export const createRouterConfig = async (
|
||||
app: ApplicationNested,
|
||||
domain: Domain,
|
||||
entryPoint: "web" | "websecure",
|
||||
) => {
|
||||
const { appName, redirects, security } = app;
|
||||
const { certificateType } = domain;
|
||||
|
||||
@@ -56,32 +80,33 @@ const createRouterConfig = async (app: ApplicationNested, domain: Domain) => {
|
||||
rule: `Host(\`${host}\`)${path ? ` && PathPrefix(\`${path}\`)` : ""}`,
|
||||
service: `${appName}-service-${uniqueConfigKey}`,
|
||||
middlewares: [],
|
||||
entryPoints: https
|
||||
? ["web", ...(process.env.NODE_ENV === "production" ? ["websecure"] : [])]
|
||||
: ["web"],
|
||||
tls: {},
|
||||
entryPoints: [entryPoint],
|
||||
};
|
||||
|
||||
if (https) {
|
||||
if (entryPoint === "web" && https) {
|
||||
routerConfig.middlewares = ["redirect-to-https"];
|
||||
}
|
||||
|
||||
// redirects
|
||||
for (const redirect of redirects) {
|
||||
const middlewareName = `redirect-${appName}-${redirect.uniqueConfigKey}`;
|
||||
routerConfig.middlewares?.push(middlewareName);
|
||||
if ((entryPoint === "websecure" && https) || !https) {
|
||||
// redirects
|
||||
for (const redirect of redirects) {
|
||||
const middlewareName = `redirect-${appName}-${redirect.uniqueConfigKey}`;
|
||||
routerConfig.middlewares?.push(middlewareName);
|
||||
}
|
||||
|
||||
// security
|
||||
if (security.length > 0) {
|
||||
const middlewareName = `auth-${appName}`;
|
||||
routerConfig.middlewares?.push(middlewareName);
|
||||
}
|
||||
}
|
||||
|
||||
// security
|
||||
if (security.length > 0) {
|
||||
const middlewareName = `auth-${appName}`;
|
||||
routerConfig.middlewares?.push(middlewareName);
|
||||
}
|
||||
|
||||
if (certificateType === "letsencrypt") {
|
||||
routerConfig.tls = { certResolver: "letsencrypt" };
|
||||
} else if (certificateType === "none") {
|
||||
routerConfig.tls = undefined;
|
||||
if (entryPoint === "websecure") {
|
||||
if (certificateType === "letsencrypt") {
|
||||
routerConfig.tls = { certResolver: "letsencrypt" };
|
||||
} else if (certificateType === "none") {
|
||||
routerConfig.tls = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return routerConfig;
|
||||
|
||||
Reference in New Issue
Block a user