added traefik config provider endpoint

This commit is contained in:
Milo Schwartz
2024-09-28 22:50:10 -04:00
parent a67463a518
commit 07bf2059c6
10 changed files with 134 additions and 472 deletions

View File

@@ -0,0 +1,52 @@
export type DynamicTraefikConfig = {
http: Http;
};
export type Http = {
routers: Routers;
services: Services;
middlewares: Middlewares;
};
export type Routers = {
[key: string]: Router;
};
export type Router = {
entryPoints: string[];
middlewares: string[];
service: string;
rule: string;
};
export type Services = {
[key: string]: Service;
};
export type Service = {
loadBalancer: LoadBalancer;
};
export type LoadBalancer = {
servers: Server[];
};
export type Server = {
url: string;
};
export type Middlewares = {
[key: string]: MiddlewarePlugin;
};
export type MiddlewarePlugin = {
plugin: Plugin;
};
export type Plugin = {
[key: string]: MiddlewarePluginConfig;
};
export type MiddlewarePluginConfig = {
[key: string]: any;
};

View File

@@ -0,0 +1,70 @@
import { Request, Response } from "express";
import db from "@server/db";
import * as schema from "@server/db/schema";
import { DynamicTraefikConfig } from "./configSchema";
import { like } from "drizzle-orm";
import logger from "@server/logger";
export async function traefikConfigProvider(_: Request, res: Response) {
try {
const targets = await getAllTargets();
const traefikConfig = buildTraefikConfig(targets);
res.status(200).send(traefikConfig);
} catch (e) {
logger.error(`Failed to build traefik config: ${e}`);
res.status(500).send({ message: "Failed to build traefik config" });
}
}
export function buildTraefikConfig(
targets: schema.Target[],
): DynamicTraefikConfig {
const middlewareName = "gerbil";
const http: DynamicTraefikConfig["http"] = {
routers: {},
services: {},
middlewares: {
[middlewareName]: {
plugin: {
[middlewareName]: {
// These are temporary values
APIEndpoint:
"http://host.docker.internal:3001/api/v1/gerbil",
ValidToken: "abc123",
},
},
},
},
};
for (const target of targets) {
const routerName = `router-${target.targetId}`;
const serviceName = `service-${target.targetId}`;
http.routers[routerName] = {
entryPoints: [target.method],
middlewares: [middlewareName],
service: serviceName,
rule: `Host(\`${target.resourceId}\`)`, // assuming resourceId is a valid full hostname
};
http.services[serviceName] = {
loadBalancer: {
servers: [
{ url: `${target.method}://${target.ip}:${target.port}` },
],
},
};
}
return { http } as DynamicTraefikConfig;
}
export async function getAllTargets(): Promise<schema.Target[]> {
const all = await db
.select()
.from(schema.targets)
.where(like(schema.targets.resourceId, "%.%")); // any resourceId with a dot is a valid hostname; otherwise it's a UUID placeholder
return all;
}