mirror of
https://github.com/fosrl/pangolin.git
synced 2026-10-30 07:29:04 +01:00
Merge branch 'dev' into feat/redirect-tables
This commit is contained in:
@@ -297,7 +297,7 @@ export class TraefikConfigManager {
|
||||
const secondsUntilExpiry =
|
||||
localState.expiresAt - nowInSeconds;
|
||||
const daysUntilExpiry = secondsUntilExpiry / (60 * 60 * 24);
|
||||
if (daysUntilExpiry < 45) {
|
||||
if (daysUntilExpiry < 15) {
|
||||
logger.info(
|
||||
`Fetching certificates due to upcoming expiry for ${domain} (${Math.round(daysUntilExpiry)} days remaining)`
|
||||
);
|
||||
@@ -314,7 +314,7 @@ export class TraefikConfigManager {
|
||||
const nowInSeconds = Math.floor(Date.now() / 1000);
|
||||
const secondsUntilExpiry = state.expiresAt - nowInSeconds;
|
||||
const daysUntilExpiry = secondsUntilExpiry / (60 * 60 * 24);
|
||||
if (daysUntilExpiry < 45) {
|
||||
if (daysUntilExpiry < 15) {
|
||||
logger.info(
|
||||
`Fetching certificates due to upcoming expiry for wildcard cert ${certDomain} (${Math.round(daysUntilExpiry)} days remaining)`
|
||||
);
|
||||
|
||||
@@ -42,6 +42,7 @@ import { buildWildcardTls } from "./certResolver";
|
||||
import { buildCustomHeadersMiddleware } from "./headersMiddleware";
|
||||
import {
|
||||
buildHttpLoadBalancerServers,
|
||||
buildLoadBalancingStrategy,
|
||||
buildStickySessionCookie,
|
||||
buildStickySessionIp,
|
||||
buildTcpUdpLoadBalancerServers
|
||||
@@ -95,6 +96,7 @@ export async function getTraefikConfig(
|
||||
domainId: resources.domainId,
|
||||
enabled: resources.enabled,
|
||||
stickySession: resources.stickySession,
|
||||
loadBalancingStrategy: resources.loadBalancingStrategy,
|
||||
tlsServerName: resources.tlsServerName,
|
||||
setHostHeader: resources.setHostHeader,
|
||||
enableProxy: resources.enableProxy,
|
||||
@@ -225,6 +227,7 @@ export async function getTraefikConfig(
|
||||
domainId: row.domainId,
|
||||
enabled: row.enabled,
|
||||
stickySession: row.stickySession,
|
||||
loadBalancingStrategy: row.loadBalancingStrategy,
|
||||
tlsServerName: row.tlsServerName,
|
||||
setHostHeader: row.setHostHeader,
|
||||
enableProxy: row.enableProxy,
|
||||
@@ -542,6 +545,9 @@ export async function getTraefikConfig(
|
||||
config_output.http.services![serviceName] = {
|
||||
loadBalancer: {
|
||||
servers: buildHttpLoadBalancerServers(targets),
|
||||
...buildLoadBalancingStrategy(
|
||||
resource.loadBalancingStrategy
|
||||
),
|
||||
...(resource.stickySession
|
||||
? buildStickySessionCookie(resource.ssl)
|
||||
: {})
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
import "@server/extendZod";
|
||||
import { assertEqualsObj } from "@test/assert";
|
||||
import {
|
||||
buildHttpLoadBalancerServers,
|
||||
buildLoadBalancingStrategy,
|
||||
buildTcpUdpLoadBalancerServers
|
||||
} from "./loadBalancer";
|
||||
import type { TargetWithSite } from "./types";
|
||||
|
||||
function makeTarget(ip: string, siteType: string): TargetWithSite {
|
||||
return {
|
||||
targetId: 1,
|
||||
resourceId: 1,
|
||||
providerId: null,
|
||||
siteId: 1,
|
||||
ip,
|
||||
port: 8080,
|
||||
internalPort: 9000,
|
||||
method: "http",
|
||||
enabled: true,
|
||||
health: "healthy",
|
||||
path: null,
|
||||
pathMatchType: null,
|
||||
rewritePath: null,
|
||||
rewritePathType: null,
|
||||
priority: 100,
|
||||
mode: "http",
|
||||
authToken: null,
|
||||
site: {
|
||||
siteId: 1,
|
||||
type: siteType,
|
||||
subnet: null,
|
||||
exitNodeId: null,
|
||||
online: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
const ipCases = [
|
||||
{ ip: "2001:db8::1", host: "[2001:db8::1]" },
|
||||
{ ip: "192.0.2.1", host: "192.0.2.1" }
|
||||
];
|
||||
const cases = [
|
||||
...ipCases,
|
||||
{ ip: "backend.example.com", host: "backend.example.com" }
|
||||
];
|
||||
|
||||
for (const { ip, host } of cases) {
|
||||
const target = makeTarget(ip, "local");
|
||||
assertEqualsObj(
|
||||
buildHttpLoadBalancerServers([target]),
|
||||
[{ url: `http://${host}:8080` }],
|
||||
`Local HTTP target ${ip} should format its endpoint`
|
||||
);
|
||||
assertEqualsObj(
|
||||
buildTcpUdpLoadBalancerServers([target]),
|
||||
[{ address: `${host}:8080` }],
|
||||
`Local TCP/UDP target ${ip} should format its endpoint`
|
||||
);
|
||||
}
|
||||
|
||||
for (const { ip, host } of ipCases) {
|
||||
const target = makeTarget("backend.example.com", "newt");
|
||||
target.site.subnet = `${ip}/${ip.includes(":") ? 128 : 32}`;
|
||||
|
||||
assertEqualsObj(
|
||||
buildHttpLoadBalancerServers([target]),
|
||||
[{ url: `http://${host}:9000` }],
|
||||
"Newt HTTP target should use the subnet endpoint and internal port"
|
||||
);
|
||||
assertEqualsObj(
|
||||
buildTcpUdpLoadBalancerServers([target]),
|
||||
[{ address: `${host}:9000` }],
|
||||
"Newt TCP/UDP target should use the subnet endpoint and internal port"
|
||||
);
|
||||
}
|
||||
|
||||
assertEqualsObj(
|
||||
buildLoadBalancingStrategy("wrr"),
|
||||
{},
|
||||
"Default wrr strategy should be omitted"
|
||||
);
|
||||
assertEqualsObj(
|
||||
buildLoadBalancingStrategy(null),
|
||||
{},
|
||||
"Missing strategy should be omitted"
|
||||
);
|
||||
for (const strategy of ["p2c", "hrw", "leasttime"]) {
|
||||
assertEqualsObj(
|
||||
buildLoadBalancingStrategy(strategy),
|
||||
{ strategy },
|
||||
`${strategy} strategy should be emitted`
|
||||
);
|
||||
}
|
||||
|
||||
console.log("All load balancer endpoint tests passed!");
|
||||
}
|
||||
|
||||
runTests();
|
||||
@@ -1,3 +1,4 @@
|
||||
import { formatEndpoint } from "@server/lib/ip";
|
||||
import { TargetWithSite } from "./types";
|
||||
|
||||
/**
|
||||
@@ -48,12 +49,12 @@ export function buildHttpLoadBalancerServers(targets: TargetWithSite[]) {
|
||||
target.site.type === "wireguard"
|
||||
) {
|
||||
return {
|
||||
url: `${target.method}://${target.ip}:${target.port}`
|
||||
url: `${target.method}://${formatEndpoint(target.ip, target.port)}`
|
||||
};
|
||||
} else if (target.site.type === "newt") {
|
||||
const ip = target.site.subnet!.split("/")[0];
|
||||
return {
|
||||
url: `${target.method}://${ip}:${target.internalPort}`
|
||||
url: `${target.method}://${formatEndpoint(ip, target.internalPort!)}`
|
||||
};
|
||||
}
|
||||
})
|
||||
@@ -62,6 +63,18 @@ export function buildHttpLoadBalancerServers(targets: TargetWithSite[]) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the loadBalancer.strategy for an HTTP-mode resource. Traefik defaults
|
||||
* to wrr when strategy is omitted, so only emit it for the non-default
|
||||
* strategies to keep the generated config unchanged for existing resources.
|
||||
*/
|
||||
export function buildLoadBalancingStrategy(strategy: string | null) {
|
||||
if (!strategy || strategy === "wrr") {
|
||||
return {};
|
||||
}
|
||||
return { strategy };
|
||||
}
|
||||
|
||||
export function buildStickySessionCookie(ssl: boolean | null) {
|
||||
return {
|
||||
sticky: {
|
||||
@@ -111,12 +124,12 @@ export function buildTcpUdpLoadBalancerServers(targets: TargetWithSite[]) {
|
||||
target.site.type === "wireguard"
|
||||
) {
|
||||
return {
|
||||
address: `${target.ip}:${target.port}`
|
||||
address: formatEndpoint(target.ip, target.port)
|
||||
};
|
||||
} else if (target.site.type === "newt") {
|
||||
const ip = target.site.subnet!.split("/")[0];
|
||||
return {
|
||||
address: `${ip}:${target.internalPort}`
|
||||
address: formatEndpoint(ip, target.internalPort!)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user