Files
Minikura/packages/k8s-operator/src/controllers/reverse-proxy-controller.ts
T

125 lines
4.0 KiB
TypeScript
Raw Normal View History

2026-02-17 18:12:02 +07:00
import type { CustomEnvironmentVariable, ReverseProxyServer } from "@minikura/db";
2026-01-16 12:32:36 +07:00
import {
createReverseProxyServer,
deleteReverseProxyServer,
} from "../resources/reverseProxyServer";
2026-02-17 18:12:02 +07:00
import type { ReverseProxyConfig } from "../types";
import { BaseController } from "./base-controller";
2025-05-12 12:34:09 +07:00
type ReverseProxyWithEnvVars = ReverseProxyServer & {
env_variables: CustomEnvironmentVariable[];
};
export class ReverseProxyController extends BaseController {
private deployedProxies = new Map<string, ReverseProxyWithEnvVars>();
protected getControllerName(): string {
2026-01-16 12:32:36 +07:00
return "ReverseProxyController";
2025-05-12 12:34:09 +07:00
}
protected async syncResources(): Promise<void> {
try {
const appsApi = this.k8sClient.getAppsApi();
const coreApi = this.k8sClient.getCoreApi();
const networkingApi = this.k8sClient.getNetworkingApi();
2026-01-16 12:32:36 +07:00
const proxies = (await this.prisma.reverseProxyServer.findMany({
2025-05-12 12:34:09 +07:00
include: {
env_variables: true,
2026-01-16 12:32:36 +07:00
},
})) as ReverseProxyWithEnvVars[];
const currentProxyIds = new Set(proxies.map((proxy) => proxy.id));
2025-05-12 12:34:09 +07:00
for (const [proxyId, proxy] of this.deployedProxies.entries()) {
if (!currentProxyIds.has(proxyId)) {
2026-02-17 18:12:02 +07:00
this.logger.info(
{ proxyId, proxyType: proxy.type },
"Reverse proxy removed from database, deleting K8s resources"
2026-01-16 12:32:36 +07:00
);
2025-05-12 12:34:09 +07:00
await deleteReverseProxyServer(proxy.id, proxy.type, appsApi, coreApi, this.namespace);
this.deployedProxies.delete(proxyId);
}
}
2026-01-16 12:32:36 +07:00
2025-05-12 12:34:09 +07:00
for (const proxy of proxies) {
const deployedProxy = this.deployedProxies.get(proxy.id);
2026-01-16 12:32:36 +07:00
2025-05-12 12:34:09 +07:00
if (!deployedProxy || this.hasProxyChanged(deployedProxy, proxy)) {
2026-02-17 18:12:02 +07:00
const action = !deployedProxy ? "Creating" : "Updating";
this.logger.info(
{
proxyId: proxy.id,
proxyType: proxy.type,
action: action.toLowerCase(),
externalAddress: proxy.external_address,
externalPort: proxy.external_port,
listenPort: proxy.listen_port,
},
`${action} reverse proxy server in Kubernetes`
2026-01-16 12:32:36 +07:00
);
2025-05-12 12:34:09 +07:00
const proxyConfig: ReverseProxyConfig = {
id: proxy.id,
external_address: proxy.external_address,
external_port: proxy.external_port,
listen_port: proxy.listen_port,
description: proxy.description,
apiKey: proxy.api_key,
type: proxy.type,
memory: proxy.memory,
2026-02-17 18:12:02 +07:00
service_type: proxy.service_type,
2026-01-16 12:32:36 +07:00
env_variables: proxy.env_variables?.map((ev) => ({
2025-05-12 12:34:09 +07:00
key: ev.key,
2026-01-16 12:32:36 +07:00
value: ev.value,
})),
2025-05-12 12:34:09 +07:00
};
2026-01-16 12:32:36 +07:00
2025-05-12 12:34:09 +07:00
await createReverseProxyServer(
2026-01-16 12:32:36 +07:00
proxyConfig,
appsApi,
coreApi,
networkingApi,
2025-05-12 12:34:09 +07:00
this.namespace
);
2026-01-16 12:32:36 +07:00
2025-05-12 12:34:09 +07:00
this.deployedProxies.set(proxy.id, { ...proxy });
}
}
} catch (error) {
2026-02-17 18:12:02 +07:00
this.logger.error({ err: error }, "Failed to sync reverse proxy servers to Kubernetes");
2025-05-12 12:34:09 +07:00
throw error;
}
}
private hasProxyChanged(
2026-01-16 12:32:36 +07:00
oldProxy: ReverseProxyWithEnvVars,
2025-05-12 12:34:09 +07:00
newProxy: ReverseProxyWithEnvVars
): boolean {
2026-01-16 12:32:36 +07:00
const basicPropsChanged =
2025-05-12 12:34:09 +07:00
oldProxy.external_address !== newProxy.external_address ||
oldProxy.external_port !== newProxy.external_port ||
oldProxy.listen_port !== newProxy.listen_port ||
2026-02-17 18:12:02 +07:00
oldProxy.description !== newProxy.description ||
2026-08-13 01:57:51 +07:00
oldProxy.service_type !== newProxy.service_type ||
oldProxy.memory !== newProxy.memory ||
oldProxy.type !== newProxy.type;
2026-01-16 12:32:36 +07:00
2025-05-12 12:34:09 +07:00
if (basicPropsChanged) return true;
2026-01-16 12:32:36 +07:00
2025-05-12 12:34:09 +07:00
const oldEnvVars = oldProxy.env_variables || [];
const newEnvVars = newProxy.env_variables || [];
2026-01-16 12:32:36 +07:00
2025-05-12 12:34:09 +07:00
if (oldEnvVars.length !== newEnvVars.length) return true;
2026-02-17 18:12:02 +07:00
2025-05-12 12:34:09 +07:00
for (const newEnv of newEnvVars) {
2026-01-16 12:32:36 +07:00
const oldEnv = oldEnvVars.find((e) => e.key === newEnv.key);
2025-05-12 12:34:09 +07:00
if (!oldEnv || oldEnv.value !== newEnv.value) {
return true;
}
}
2026-01-16 12:32:36 +07:00
2025-05-12 12:34:09 +07:00
return false;
}
2026-01-16 12:32:36 +07:00
}