mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-10 12:46:37 +00:00
Adjust algo for showing maintence page
This commit is contained in:
@@ -19,15 +19,16 @@ import { sanitize, validatePathRewriteConfig } from "./utils";
|
|||||||
const redirectHttpsMiddlewareName = "redirect-to-https";
|
const redirectHttpsMiddlewareName = "redirect-to-https";
|
||||||
const badgerMiddlewareName = "badger";
|
const badgerMiddlewareName = "badger";
|
||||||
|
|
||||||
export async function getTraefikConfig(
|
|
||||||
exitNodeId: number,
|
|
||||||
siteTypes: string[],
|
|
||||||
filterOutNamespaceDomains = false,
|
|
||||||
generateLoginPageRouters = false,
|
|
||||||
allowRawResources = true
|
|
||||||
): Promise<any> {
|
|
||||||
// Define extended target type with site information
|
// Define extended target type with site information
|
||||||
type TargetWithSite = Target & {
|
type TargetWithSite = Target & {
|
||||||
|
resourceId: number;
|
||||||
|
targetId: number;
|
||||||
|
ip: string | null;
|
||||||
|
method: string | null;
|
||||||
|
port: number | null;
|
||||||
|
internalPort: number | null;
|
||||||
|
enabled: boolean;
|
||||||
|
health: string | null;
|
||||||
site: {
|
site: {
|
||||||
siteId: number;
|
siteId: number;
|
||||||
type: string;
|
type: string;
|
||||||
@@ -37,6 +38,13 @@ export async function getTraefikConfig(
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export async function getTraefikConfig(
|
||||||
|
exitNodeId: number,
|
||||||
|
siteTypes: string[],
|
||||||
|
filterOutNamespaceDomains = false,
|
||||||
|
generateLoginPageRouters = false,
|
||||||
|
allowRawResources = true
|
||||||
|
): Promise<any> {
|
||||||
// Get resources with their targets and sites in a single optimized query
|
// Get resources with their targets and sites in a single optimized query
|
||||||
// Start from sites on this exit node, then join to targets and resources
|
// Start from sites on this exit node, then join to targets and resources
|
||||||
const resourcesWithTargetsAndSites = await db
|
const resourcesWithTargetsAndSites = await db
|
||||||
@@ -104,10 +112,6 @@ export async function getTraefikConfig(
|
|||||||
eq(sites.type, "local")
|
eq(sites.type, "local")
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
or(
|
|
||||||
ne(targetHealthCheck.hcHealth, "unhealthy"), // Exclude unhealthy targets
|
|
||||||
isNull(targetHealthCheck.hcHealth) // Include targets with no health check record
|
|
||||||
),
|
|
||||||
inArray(sites.type, siteTypes),
|
inArray(sites.type, siteTypes),
|
||||||
allowRawResources
|
allowRawResources
|
||||||
? isNotNull(resources.http) // ignore the http check if allow_raw_resources is true
|
? isNotNull(resources.http) // ignore the http check if allow_raw_resources is true
|
||||||
@@ -193,6 +197,7 @@ export async function getTraefikConfig(
|
|||||||
port: row.port,
|
port: row.port,
|
||||||
internalPort: row.internalPort,
|
internalPort: row.internalPort,
|
||||||
enabled: row.targetEnabled,
|
enabled: row.targetEnabled,
|
||||||
|
health: row.hcHealth,
|
||||||
site: {
|
site: {
|
||||||
siteId: row.siteId,
|
siteId: row.siteId,
|
||||||
type: row.siteType,
|
type: row.siteType,
|
||||||
@@ -222,7 +227,7 @@ export async function getTraefikConfig(
|
|||||||
|
|
||||||
// get the key and the resource
|
// get the key and the resource
|
||||||
for (const [key, resource] of resourcesMap.entries()) {
|
for (const [key, resource] of resourcesMap.entries()) {
|
||||||
const targets = resource.targets;
|
const targets = resource.targets as TargetWithSite[];
|
||||||
|
|
||||||
const routerName = `${key}-${resource.name}-router`;
|
const routerName = `${key}-${resource.name}-router`;
|
||||||
const serviceName = `${key}-${resource.name}-service`;
|
const serviceName = `${key}-${resource.name}-service`;
|
||||||
@@ -471,16 +476,20 @@ export async function getTraefikConfig(
|
|||||||
|
|
||||||
// TODO: HOW TO HANDLE ^^^^^^ BETTER
|
// TODO: HOW TO HANDLE ^^^^^^ BETTER
|
||||||
const anySitesOnline = (
|
const anySitesOnline = (
|
||||||
targets as TargetWithSite[]
|
targets
|
||||||
).some((target: TargetWithSite) => target.site.online);
|
).some((target) => target.site.online);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(targets as TargetWithSite[])
|
targets
|
||||||
.filter((target: TargetWithSite) => {
|
.filter((target) => {
|
||||||
if (!target.enabled) {
|
if (!target.enabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target.health == "unhealthy") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If any sites are online, exclude offline sites
|
// If any sites are online, exclude offline sites
|
||||||
if (anySitesOnline && !target.site.online) {
|
if (anySitesOnline && !target.site.online) {
|
||||||
return false;
|
return false;
|
||||||
@@ -508,7 +517,7 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.map((target: TargetWithSite) => {
|
.map((target) => {
|
||||||
if (
|
if (
|
||||||
target.site.type === "local" ||
|
target.site.type === "local" ||
|
||||||
target.site.type === "wireguard"
|
target.site.type === "wireguard"
|
||||||
@@ -595,11 +604,11 @@ export async function getTraefikConfig(
|
|||||||
servers: (() => {
|
servers: (() => {
|
||||||
// Check if any sites are online
|
// Check if any sites are online
|
||||||
const anySitesOnline = (
|
const anySitesOnline = (
|
||||||
targets as TargetWithSite[]
|
targets
|
||||||
).some((target: TargetWithSite) => target.site.online);
|
).some((target) => target.site.online);
|
||||||
|
|
||||||
return (targets as TargetWithSite[])
|
return targets
|
||||||
.filter((target: TargetWithSite) => {
|
.filter((target) => {
|
||||||
if (!target.enabled) {
|
if (!target.enabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -626,7 +635,7 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.map((target: TargetWithSite) => {
|
.map((target) => {
|
||||||
if (
|
if (
|
||||||
target.site.type === "local" ||
|
target.site.type === "local" ||
|
||||||
target.site.type === "wireguard"
|
target.site.type === "wireguard"
|
||||||
|
|||||||
@@ -47,15 +47,16 @@ const redirectHttpsMiddlewareName = "redirect-to-https";
|
|||||||
const redirectToRootMiddlewareName = "redirect-to-root";
|
const redirectToRootMiddlewareName = "redirect-to-root";
|
||||||
const badgerMiddlewareName = "badger";
|
const badgerMiddlewareName = "badger";
|
||||||
|
|
||||||
export async function getTraefikConfig(
|
|
||||||
exitNodeId: number,
|
|
||||||
siteTypes: string[],
|
|
||||||
filterOutNamespaceDomains = false,
|
|
||||||
generateLoginPageRouters = false,
|
|
||||||
allowRawResources = true
|
|
||||||
): Promise<any> {
|
|
||||||
// Define extended target type with site information
|
// Define extended target type with site information
|
||||||
type TargetWithSite = Target & {
|
type TargetWithSite = Target & {
|
||||||
|
resourceId: number;
|
||||||
|
targetId: number;
|
||||||
|
ip: string | null;
|
||||||
|
method: string | null;
|
||||||
|
port: number | null;
|
||||||
|
internalPort: number | null;
|
||||||
|
enabled: boolean;
|
||||||
|
health: string | null;
|
||||||
site: {
|
site: {
|
||||||
siteId: number;
|
siteId: number;
|
||||||
type: string;
|
type: string;
|
||||||
@@ -65,6 +66,14 @@ export async function getTraefikConfig(
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export async function getTraefikConfig(
|
||||||
|
exitNodeId: number,
|
||||||
|
siteTypes: string[],
|
||||||
|
filterOutNamespaceDomains = false,
|
||||||
|
generateLoginPageRouters = false,
|
||||||
|
allowRawResources = true
|
||||||
|
): Promise<any> {
|
||||||
|
|
||||||
// Get resources with their targets and sites in a single optimized query
|
// Get resources with their targets and sites in a single optimized query
|
||||||
// Start from sites on this exit node, then join to targets and resources
|
// Start from sites on this exit node, then join to targets and resources
|
||||||
const resourcesWithTargetsAndSites = await db
|
const resourcesWithTargetsAndSites = await db
|
||||||
@@ -147,10 +156,6 @@ export async function getTraefikConfig(
|
|||||||
sql`(${build != "saas" ? 1 : 0} = 1)` // Dont allow undefined local sites in cloud
|
sql`(${build != "saas" ? 1 : 0} = 1)` // Dont allow undefined local sites in cloud
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
or(
|
|
||||||
ne(targetHealthCheck.hcHealth, "unhealthy"), // Exclude unhealthy targets
|
|
||||||
isNull(targetHealthCheck.hcHealth) // Include targets with no health check record
|
|
||||||
),
|
|
||||||
inArray(sites.type, siteTypes),
|
inArray(sites.type, siteTypes),
|
||||||
allowRawResources
|
allowRawResources
|
||||||
? isNotNull(resources.http) // ignore the http check if allow_raw_resources is true
|
? isNotNull(resources.http) // ignore the http check if allow_raw_resources is true
|
||||||
@@ -233,7 +238,7 @@ export async function getTraefikConfig(
|
|||||||
maintenanceModeType: row.maintenanceModeType,
|
maintenanceModeType: row.maintenanceModeType,
|
||||||
maintenanceTitle: row.maintenanceTitle,
|
maintenanceTitle: row.maintenanceTitle,
|
||||||
maintenanceMessage: row.maintenanceMessage,
|
maintenanceMessage: row.maintenanceMessage,
|
||||||
maintenanceEstimatedTime: row.maintenanceEstimatedTime,
|
maintenanceEstimatedTime: row.maintenanceEstimatedTime
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,6 +251,7 @@ export async function getTraefikConfig(
|
|||||||
port: row.port,
|
port: row.port,
|
||||||
internalPort: row.internalPort,
|
internalPort: row.internalPort,
|
||||||
enabled: row.targetEnabled,
|
enabled: row.targetEnabled,
|
||||||
|
health: row.hcHealth,
|
||||||
site: {
|
site: {
|
||||||
siteId: row.siteId,
|
siteId: row.siteId,
|
||||||
type: row.siteType,
|
type: row.siteType,
|
||||||
@@ -291,7 +297,7 @@ export async function getTraefikConfig(
|
|||||||
|
|
||||||
// get the key and the resource
|
// get the key and the resource
|
||||||
for (const [key, resource] of resourcesMap.entries()) {
|
for (const [key, resource] of resourcesMap.entries()) {
|
||||||
const targets = resource.targets;
|
const targets = resource.targets as TargetWithSite[];
|
||||||
|
|
||||||
const routerName = `${key}-${resource.name}-router`;
|
const routerName = `${key}-${resource.name}-router`;
|
||||||
const serviceName = `${key}-${resource.name}-service`;
|
const serviceName = `${key}-${resource.name}-service`;
|
||||||
@@ -429,21 +435,15 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const availableServers = (targets as TargetWithSite[]).filter(
|
const availableServers = targets.filter(
|
||||||
(target: TargetWithSite) => {
|
(target) => {
|
||||||
if (!target.enabled) return false;
|
if (!target.enabled) return false;
|
||||||
|
|
||||||
const anySitesOnline = (targets as TargetWithSite[]).some(
|
if (!target.site.online) return false;
|
||||||
(t: TargetWithSite) => t.site.online
|
|
||||||
);
|
|
||||||
if (anySitesOnline && !target.site.online) return false;
|
|
||||||
|
|
||||||
if (target.site.type === "local" || target.site.type === "wireguard") {
|
if (target.health == "unhealthy") return false;
|
||||||
return target.ip && target.port && target.method;
|
|
||||||
} else if (target.site.type === "newt") {
|
return true;
|
||||||
return target.internalPort && target.method && target.site.subnet;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -471,8 +471,10 @@ export async function getTraefikConfig(
|
|||||||
const maintenanceRouterName = `${key}-maintenance-router`;
|
const maintenanceRouterName = `${key}-maintenance-router`;
|
||||||
const rewriteMiddlewareName = `${key}-maintenance-rewrite`;
|
const rewriteMiddlewareName = `${key}-maintenance-rewrite`;
|
||||||
|
|
||||||
const entrypointHttp = config.getRawConfig().traefik.http_entrypoint;
|
const entrypointHttp =
|
||||||
const entrypointHttps = config.getRawConfig().traefik.https_entrypoint;
|
config.getRawConfig().traefik.http_entrypoint;
|
||||||
|
const entrypointHttps =
|
||||||
|
config.getRawConfig().traefik.https_entrypoint;
|
||||||
|
|
||||||
const fullDomain = resource.fullDomain;
|
const fullDomain = resource.fullDomain;
|
||||||
const domainParts = fullDomain.split(".");
|
const domainParts = fullDomain.split(".");
|
||||||
@@ -481,11 +483,16 @@ export async function getTraefikConfig(
|
|||||||
: fullDomain;
|
: fullDomain;
|
||||||
|
|
||||||
const maintenancePort = config.getRawConfig().server.next_port;
|
const maintenancePort = config.getRawConfig().server.next_port;
|
||||||
const maintenanceHost = config.getRawConfig().server.internal_hostname;
|
const maintenanceHost =
|
||||||
|
config.getRawConfig().server.internal_hostname;
|
||||||
|
|
||||||
config_output.http.services[maintenanceServiceName] = {
|
config_output.http.services[maintenanceServiceName] = {
|
||||||
loadBalancer: {
|
loadBalancer: {
|
||||||
servers: [{ url: `http://${maintenanceHost}:${maintenancePort}` }],
|
servers: [
|
||||||
|
{
|
||||||
|
url: `http://${maintenanceHost}:${maintenancePort}`
|
||||||
|
}
|
||||||
|
],
|
||||||
passHostHeader: true
|
passHostHeader: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -503,7 +510,9 @@ export async function getTraefikConfig(
|
|||||||
};
|
};
|
||||||
|
|
||||||
config_output.http.routers[maintenanceRouterName] = {
|
config_output.http.routers[maintenanceRouterName] = {
|
||||||
entryPoints: [resource.ssl ? entrypointHttps : entrypointHttp],
|
entryPoints: [
|
||||||
|
resource.ssl ? entrypointHttps : entrypointHttp
|
||||||
|
],
|
||||||
service: maintenanceServiceName,
|
service: maintenanceServiceName,
|
||||||
middlewares: [rewriteMiddlewareName],
|
middlewares: [rewriteMiddlewareName],
|
||||||
rule: rule,
|
rule: rule,
|
||||||
@@ -512,8 +521,11 @@ export async function getTraefikConfig(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Router to allow Next.js assets to load without rewrite
|
// Router to allow Next.js assets to load without rewrite
|
||||||
config_output.http.routers[`${maintenanceRouterName}-assets`] = {
|
config_output.http.routers[`${maintenanceRouterName}-assets`] =
|
||||||
entryPoints: [resource.ssl ? entrypointHttps : entrypointHttp],
|
{
|
||||||
|
entryPoints: [
|
||||||
|
resource.ssl ? entrypointHttps : entrypointHttp
|
||||||
|
],
|
||||||
service: maintenanceServiceName,
|
service: maintenanceServiceName,
|
||||||
rule: `Host(\`${fullDomain}\`) && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`))`,
|
rule: `Host(\`${fullDomain}\`) && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`))`,
|
||||||
priority: 2001,
|
priority: 2001,
|
||||||
@@ -654,17 +666,21 @@ export async function getTraefikConfig(
|
|||||||
// RECEIVE BANDWIDTH ENDPOINT.
|
// RECEIVE BANDWIDTH ENDPOINT.
|
||||||
|
|
||||||
// TODO: HOW TO HANDLE ^^^^^^ BETTER
|
// TODO: HOW TO HANDLE ^^^^^^ BETTER
|
||||||
const anySitesOnline = (
|
const anySitesOnline = targets.some(
|
||||||
targets as TargetWithSite[]
|
(target) => target.site.online
|
||||||
).some((target: TargetWithSite) => target.site.online);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(targets as TargetWithSite[])
|
targets
|
||||||
.filter((target: TargetWithSite) => {
|
.filter((target) => {
|
||||||
if (!target.enabled) {
|
if (!target.enabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target.health == "unhealthy") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If any sites are online, exclude offline sites
|
// If any sites are online, exclude offline sites
|
||||||
if (anySitesOnline && !target.site.online) {
|
if (anySitesOnline && !target.site.online) {
|
||||||
return false;
|
return false;
|
||||||
@@ -692,7 +708,7 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.map((target: TargetWithSite) => {
|
.map((target) => {
|
||||||
if (
|
if (
|
||||||
target.site.type === "local" ||
|
target.site.type === "local" ||
|
||||||
target.site.type === "wireguard"
|
target.site.type === "wireguard"
|
||||||
@@ -779,11 +795,11 @@ export async function getTraefikConfig(
|
|||||||
servers: (() => {
|
servers: (() => {
|
||||||
// Check if any sites are online
|
// Check if any sites are online
|
||||||
const anySitesOnline = (
|
const anySitesOnline = (
|
||||||
targets as TargetWithSite[]
|
targets
|
||||||
).some((target: TargetWithSite) => target.site.online);
|
).some((target) => target.site.online);
|
||||||
|
|
||||||
return (targets as TargetWithSite[])
|
return targets
|
||||||
.filter((target: TargetWithSite) => {
|
.filter((target) => {
|
||||||
if (!target.enabled) {
|
if (!target.enabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -810,7 +826,7 @@ export async function getTraefikConfig(
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.map((target: TargetWithSite) => {
|
.map((target) => {
|
||||||
if (
|
if (
|
||||||
target.site.type === "local" ||
|
target.site.type === "local" ||
|
||||||
target.site.type === "wireguard"
|
target.site.type === "wireguard"
|
||||||
@@ -888,7 +904,8 @@ export async function getTraefikConfig(
|
|||||||
loadBalancer: {
|
loadBalancer: {
|
||||||
servers: [
|
servers: [
|
||||||
{
|
{
|
||||||
url: `http://${config.getRawConfig().server
|
url: `http://${
|
||||||
|
config.getRawConfig().server
|
||||||
.internal_hostname
|
.internal_hostname
|
||||||
}:${config.getRawConfig().server.next_port}`
|
}:${config.getRawConfig().server.next_port}`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user