mirror of
https://github.com/YuzuZensai/Minikura.git
synced 2026-09-13 10:49:21 +00:00
🐛 fix: restore plugin auth and proxy connection info
This commit is contained in:
@@ -17,6 +17,10 @@ const operatorResourceSync = new OperatorResourceSync();
|
|||||||
|
|
||||||
export const userService = new UserService(userRepo);
|
export const userService = new UserService(userRepo);
|
||||||
export const serverService = new ServerService(serverRepo, k8sService, operatorResourceSync);
|
export const serverService = new ServerService(serverRepo, k8sService, operatorResourceSync);
|
||||||
export const reverseProxyService = new ReverseProxyService(reverseProxyRepo, operatorResourceSync);
|
export const reverseProxyService = new ReverseProxyService(
|
||||||
|
reverseProxyRepo,
|
||||||
|
k8sService,
|
||||||
|
operatorResourceSync
|
||||||
|
);
|
||||||
export const wsService = webSocketService;
|
export const wsService = webSocketService;
|
||||||
export { k8sService, operatorResourceSync };
|
export { k8sService, operatorResourceSync };
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ export interface IReverseProxyService {
|
|||||||
setEnvVariable(proxyId: string, key: string, value: string): Promise<void>;
|
setEnvVariable(proxyId: string, key: string, value: string): Promise<void>;
|
||||||
getEnvVariables(proxyId: string): Promise<EnvVariable[]>;
|
getEnvVariables(proxyId: string): Promise<EnvVariable[]>;
|
||||||
deleteEnvVariable(proxyId: string, key: string): Promise<void>;
|
deleteEnvVariable(proxyId: string, key: string): Promise<void>;
|
||||||
|
getConnectionInfo(proxyId: string): Promise<unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ import type {
|
|||||||
ReverseProxyRepository,
|
ReverseProxyRepository,
|
||||||
ReverseProxyUpdateInput,
|
ReverseProxyUpdateInput,
|
||||||
} from "../../domain/repositories/reverse-proxy.repository";
|
} from "../../domain/repositories/reverse-proxy.repository";
|
||||||
import type { OperatorResourceSync } from "../../services/operator-resource-sync";
|
import type { K8sService } from "../../services/k8s";
|
||||||
|
import {
|
||||||
|
type OperatorResourceSync,
|
||||||
|
operatorResourceName,
|
||||||
|
} from "../../services/operator-resource-sync";
|
||||||
import type { IReverseProxyService } from "../interfaces/reverse-proxy.service.interface";
|
import type { IReverseProxyService } from "../interfaces/reverse-proxy.service.interface";
|
||||||
import { BaseCrudService } from "./base-crud.service";
|
import { BaseCrudService } from "./base-crud.service";
|
||||||
|
|
||||||
@@ -29,6 +33,7 @@ export class ReverseProxyService
|
|||||||
{
|
{
|
||||||
constructor(
|
constructor(
|
||||||
reverseProxyRepo: ReverseProxyRepository,
|
reverseProxyRepo: ReverseProxyRepository,
|
||||||
|
private k8sService: K8sService,
|
||||||
private operatorResourceSync: OperatorResourceSync
|
private operatorResourceSync: OperatorResourceSync
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
@@ -79,4 +84,10 @@ export class ReverseProxyService
|
|||||||
await super.deleteEnvVariable(proxyId, key);
|
await super.deleteEnvVariable(proxyId, key);
|
||||||
await this.operatorResourceSync.syncReverseProxyById(proxyId);
|
await this.operatorResourceSync.syncReverseProxyById(proxyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getConnectionInfo(proxyId: string) {
|
||||||
|
const proxy = await this.getReverseProxyById(proxyId);
|
||||||
|
const serviceName = `${String(proxy.type).toLowerCase()}-${operatorResourceName(proxyId)}`;
|
||||||
|
return this.k8sService.getServerConnectionInfo(serviceName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { authPlugin } from "./middleware/auth-plugin";
|
|||||||
import { errorHandler } from "./middleware/error-handler";
|
import { errorHandler } from "./middleware/error-handler";
|
||||||
import { bootstrapRoutes } from "./routes/bootstrap";
|
import { bootstrapRoutes } from "./routes/bootstrap";
|
||||||
import { k8sRoutes } from "./routes/k8s";
|
import { k8sRoutes } from "./routes/k8s";
|
||||||
|
import { pluginRoutes } from "./routes/plugin";
|
||||||
import { reverseProxyRoutes } from "./routes/reverse-proxy";
|
import { reverseProxyRoutes } from "./routes/reverse-proxy";
|
||||||
import { serverRoutes } from "./routes/servers";
|
import { serverRoutes } from "./routes/servers";
|
||||||
import { terminalRoutes } from "./routes/terminal";
|
import { terminalRoutes } from "./routes/terminal";
|
||||||
@@ -34,7 +35,13 @@ const app = new Elysia({ adapter: node() })
|
|||||||
.use(bootstrapRoutes)
|
.use(bootstrapRoutes)
|
||||||
.use(authPlugin)
|
.use(authPlugin)
|
||||||
.group("/api", (app) =>
|
.group("/api", (app) =>
|
||||||
app.use(userRoutes).use(serverRoutes).use(reverseProxyRoutes).use(k8sRoutes).use(terminalRoutes)
|
app
|
||||||
|
.use(userRoutes)
|
||||||
|
.use(serverRoutes)
|
||||||
|
.use(reverseProxyRoutes)
|
||||||
|
.use(pluginRoutes)
|
||||||
|
.use(k8sRoutes)
|
||||||
|
.use(terminalRoutes)
|
||||||
);
|
);
|
||||||
|
|
||||||
export type App = typeof app;
|
export type App = typeof app;
|
||||||
|
|||||||
@@ -12,18 +12,18 @@ eventBus.subscribe(ReverseProxyCreatedEvent, async (event) => {
|
|||||||
{ proxyId: event.proxyId, proxyType: event.proxyType },
|
{ proxyId: event.proxyId, proxyType: event.proxyType },
|
||||||
"Reverse proxy created event"
|
"Reverse proxy created event"
|
||||||
);
|
);
|
||||||
wsService.broadcast("create", event.proxyType, event.proxyId);
|
wsService.broadcast("CREATE", event.proxyType, event.proxyId);
|
||||||
await operatorResourceSync.syncReverseProxyById(event.proxyId);
|
await operatorResourceSync.syncReverseProxyById(event.proxyId);
|
||||||
});
|
});
|
||||||
|
|
||||||
eventBus.subscribe(ReverseProxyUpdatedEvent, async (event) => {
|
eventBus.subscribe(ReverseProxyUpdatedEvent, async (event) => {
|
||||||
logger.info({ proxyId: event.proxyId }, "Reverse proxy updated event");
|
logger.info({ proxyId: event.proxyId }, "Reverse proxy updated event");
|
||||||
wsService.broadcast("update", "reverse-proxy", event.proxyId);
|
wsService.broadcast("UPDATE", "reverse-proxy", event.proxyId);
|
||||||
await operatorResourceSync.syncReverseProxyById(event.proxyId);
|
await operatorResourceSync.syncReverseProxyById(event.proxyId);
|
||||||
});
|
});
|
||||||
|
|
||||||
eventBus.subscribe(ReverseProxyDeletedEvent, async (event) => {
|
eventBus.subscribe(ReverseProxyDeletedEvent, async (event) => {
|
||||||
logger.info({ proxyId: event.proxyId }, "Reverse proxy deleted event");
|
logger.info({ proxyId: event.proxyId }, "Reverse proxy deleted event");
|
||||||
wsService.broadcast("delete", "reverse-proxy", event.proxyId);
|
wsService.broadcast("DELETE", "reverse-proxy", event.proxyId);
|
||||||
await operatorResourceSync.deleteReverseProxy(event.proxyId);
|
await operatorResourceSync.deleteReverseProxy(event.proxyId);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,18 +9,18 @@ import { logger } from "../logger";
|
|||||||
|
|
||||||
eventBus.subscribe(ServerCreatedEvent, async (event) => {
|
eventBus.subscribe(ServerCreatedEvent, async (event) => {
|
||||||
logger.info({ serverId: event.serverId, serverType: event.serverType }, "Server created event");
|
logger.info({ serverId: event.serverId, serverType: event.serverType }, "Server created event");
|
||||||
wsService.broadcast("create", event.serverType, event.serverId);
|
wsService.broadcast("CREATE", event.serverType, event.serverId);
|
||||||
await operatorResourceSync.syncServerById(event.serverId);
|
await operatorResourceSync.syncServerById(event.serverId);
|
||||||
});
|
});
|
||||||
|
|
||||||
eventBus.subscribe(ServerUpdatedEvent, async (event) => {
|
eventBus.subscribe(ServerUpdatedEvent, async (event) => {
|
||||||
logger.info({ serverId: event.serverId }, "Server updated event");
|
logger.info({ serverId: event.serverId }, "Server updated event");
|
||||||
wsService.broadcast("update", "server", event.serverId);
|
wsService.broadcast("UPDATE", "server", event.serverId);
|
||||||
await operatorResourceSync.syncServerById(event.serverId);
|
await operatorResourceSync.syncServerById(event.serverId);
|
||||||
});
|
});
|
||||||
|
|
||||||
eventBus.subscribe(ServerDeletedEvent, async (event) => {
|
eventBus.subscribe(ServerDeletedEvent, async (event) => {
|
||||||
logger.info({ serverId: event.serverId }, "Server deleted event");
|
logger.info({ serverId: event.serverId }, "Server deleted event");
|
||||||
wsService.broadcast("delete", "server", event.serverId);
|
wsService.broadcast("DELETE", "server", event.serverId);
|
||||||
await operatorResourceSync.deleteServer(event.serverId);
|
await operatorResourceSync.deleteServer(event.serverId);
|
||||||
});
|
});
|
||||||
|
|||||||
+3
-3
@@ -64,12 +64,12 @@ export class PrismaReverseProxyRepository implements ReverseProxyRepository {
|
|||||||
description: input.description ?? null,
|
description: input.description ?? null,
|
||||||
external_address: input.external_address,
|
external_address: input.external_address,
|
||||||
external_port: input.external_port,
|
external_port: input.external_port,
|
||||||
listen_port: input.listen_port ?? 25577,
|
listen_port: input.listen_port ?? 25565,
|
||||||
service_type: input.service_type ?? "LOAD_BALANCER",
|
service_type: input.service_type ?? "LOAD_BALANCER",
|
||||||
node_port: input.node_port ?? null,
|
node_port: input.node_port ?? null,
|
||||||
memory: input.memory ?? 512,
|
memory: input.memory ?? 512,
|
||||||
cpu_request: input.cpu_request ?? "100m",
|
cpu_request: input.cpu_request ?? "250m",
|
||||||
cpu_limit: input.cpu_limit ?? "200m",
|
cpu_limit: input.cpu_limit ?? "500m",
|
||||||
api_key: token,
|
api_key: token,
|
||||||
env_variables: input.env_variables
|
env_variables: input.env_variables
|
||||||
? {
|
? {
|
||||||
|
|||||||
@@ -67,12 +67,12 @@ export class PrismaServerRepository implements ServerRepository {
|
|||||||
node_port: input.node_port ?? null,
|
node_port: input.node_port ?? null,
|
||||||
memory: input.memory ?? 2048,
|
memory: input.memory ?? 2048,
|
||||||
memory_request: input.memory_request ?? 1024,
|
memory_request: input.memory_request ?? 1024,
|
||||||
cpu_request: input.cpu_request ?? "250m",
|
cpu_request: input.cpu_request ?? "500m",
|
||||||
cpu_limit: input.cpu_limit ?? "500m",
|
cpu_limit: input.cpu_limit ?? "2",
|
||||||
jar_type: input.jar_type ?? "PAPER",
|
jar_type: input.jar_type ?? "VANILLA",
|
||||||
minecraft_version: input.minecraft_version ?? "LATEST",
|
minecraft_version: input.minecraft_version ?? "LATEST",
|
||||||
jvm_opts: input.jvm_opts ?? null,
|
jvm_opts: input.jvm_opts ?? null,
|
||||||
use_aikar_flags: input.use_aikar_flags ?? true,
|
use_aikar_flags: input.use_aikar_flags ?? false,
|
||||||
use_meowice_flags: input.use_meowice_flags ?? false,
|
use_meowice_flags: input.use_meowice_flags ?? false,
|
||||||
difficulty: input.difficulty ?? "EASY",
|
difficulty: input.difficulty ?? "EASY",
|
||||||
game_mode: input.game_mode ?? "SURVIVAL",
|
game_mode: input.game_mode ?? "SURVIVAL",
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { prisma } from "@minikura/db";
|
||||||
|
|
||||||
|
export async function findApiKeyOwner(apiKey: string) {
|
||||||
|
if (!apiKey) return null;
|
||||||
|
|
||||||
|
const [server, proxy] = await Promise.all([
|
||||||
|
prisma.server.findUnique({ where: { api_key: apiKey }, select: { id: true } }),
|
||||||
|
prisma.reverseProxyServer.findUnique({ where: { api_key: apiKey }, select: { id: true } }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (server) return { kind: "server" as const, id: server.id };
|
||||||
|
if (proxy) return { kind: "reverse-proxy" as const, id: proxy.id };
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bearerToken(header: string | null): string {
|
||||||
|
if (!header?.startsWith("Bearer ")) return "";
|
||||||
|
return header.slice(7).trim();
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { Elysia } from "elysia";
|
||||||
|
import { reverseProxyService, serverService } from "../application/di-container";
|
||||||
|
import { requirePluginApiKey } from "../middleware/auth-guards";
|
||||||
|
|
||||||
|
export const pluginRoutes = new Elysia({ prefix: "/plugin" })
|
||||||
|
.use(requirePluginApiKey)
|
||||||
|
.get("/servers", async () => serverService.getAllServers(true))
|
||||||
|
.get("/reverse-proxy", async () => reverseProxyService.getAllReverseProxies(true));
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
import { Elysia } from "elysia";
|
import { Elysia } from "elysia";
|
||||||
import { z } from "zod";
|
|
||||||
import { reverseProxyService } from "../application/di-container";
|
import { reverseProxyService } from "../application/di-container";
|
||||||
import { requireAuth } from "../middleware/auth-guards";
|
import { requireAuth } from "../middleware/auth-guards";
|
||||||
import { createReverseProxySchema, updateReverseProxySchema } from "../schemas/server.schema";
|
import {
|
||||||
|
createReverseProxySchema,
|
||||||
const envVariableSchema = z.object({
|
envVariableSchema,
|
||||||
key: z.string(),
|
updateReverseProxySchema,
|
||||||
value: z.string(),
|
} from "../schemas/server.schema";
|
||||||
});
|
|
||||||
|
|
||||||
export const reverseProxyRoutes = new Elysia({ prefix: "/reverse-proxy" })
|
export const reverseProxyRoutes = new Elysia({ prefix: "/reverse-proxy" })
|
||||||
.use(requireAuth)
|
.use(requireAuth)
|
||||||
@@ -19,6 +17,10 @@ export const reverseProxyRoutes = new Elysia({ prefix: "/reverse-proxy" })
|
|||||||
return await reverseProxyService.getReverseProxyById(params.id, false);
|
return await reverseProxyService.getReverseProxyById(params.id, false);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.get("/:id/connection-info", async ({ params }) => {
|
||||||
|
return await reverseProxyService.getConnectionInfo(params.id);
|
||||||
|
})
|
||||||
|
|
||||||
.post("/", async ({ body }) => {
|
.post("/", async ({ body }) => {
|
||||||
const payload = createReverseProxySchema.parse(body);
|
const payload = createReverseProxySchema.parse(body);
|
||||||
const proxy = await reverseProxyService.createReverseProxy(payload);
|
const proxy = await reverseProxyService.createReverseProxy(payload);
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
import { Elysia } from "elysia";
|
import { Elysia } from "elysia";
|
||||||
import { z } from "zod";
|
|
||||||
import { serverService, wsService } from "../application/di-container";
|
import { serverService, wsService } from "../application/di-container";
|
||||||
|
import { findApiKeyOwner } from "../middleware/api-key";
|
||||||
import { requireAuth } from "../middleware/auth-guards";
|
import { requireAuth } from "../middleware/auth-guards";
|
||||||
import { createServerSchema, updateServerSchema } from "../schemas/server.schema";
|
import {
|
||||||
|
createServerSchema,
|
||||||
|
envVariableSchema,
|
||||||
|
updateServerSchema,
|
||||||
|
} from "../schemas/server.schema";
|
||||||
import type { WebSocketClient } from "../services/websocket";
|
import type { WebSocketClient } from "../services/websocket";
|
||||||
|
|
||||||
const envVariableSchema = z.object({
|
|
||||||
key: z.string(),
|
|
||||||
value: z.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const serverRoutes = new Elysia({ prefix: "/servers" })
|
export const serverRoutes = new Elysia({ prefix: "/servers" })
|
||||||
.ws("/ws", {
|
.ws("/ws", {
|
||||||
open(ws: WebSocketClient & { data?: { query?: Record<string, string> }; close: () => void }) {
|
async open(
|
||||||
if (!ws.data?.query?.apiKey) {
|
ws: WebSocketClient & { data?: { query?: Record<string, string> }; close: () => void }
|
||||||
|
) {
|
||||||
|
const owner = await findApiKeyOwner(ws.data?.query?.apiKey ?? "");
|
||||||
|
if (!owner) {
|
||||||
ws.close();
|
ws.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { getErrorMessage } from "@minikura/shared/errors";
|
|||||||
import { Elysia } from "elysia";
|
import { Elysia } from "elysia";
|
||||||
import { k8sService } from "../application/di-container";
|
import { k8sService } from "../application/di-container";
|
||||||
import { logger } from "../infrastructure/logger";
|
import { logger } from "../infrastructure/logger";
|
||||||
|
import { requireAuth } from "../middleware/auth-guards";
|
||||||
|
|
||||||
type TerminalWsData = {
|
type TerminalWsData = {
|
||||||
query?: Record<string, string>;
|
query?: Record<string, string>;
|
||||||
@@ -25,7 +26,7 @@ type BunTlsOptions = {
|
|||||||
ca?: string;
|
ca?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const terminalRoutes = new Elysia({ prefix: "/terminal" }).ws("/exec", {
|
export const terminalRoutes = new Elysia({ prefix: "/terminal" }).use(requireAuth).ws("/exec", {
|
||||||
open: async (ws: TerminalWs) => {
|
open: async (ws: TerminalWs) => {
|
||||||
const podName = ws.data.query?.podName;
|
const podName = ws.data.query?.podName;
|
||||||
const container = ws.data.query?.container;
|
const container = ws.data.query?.container;
|
||||||
|
|||||||
@@ -1,29 +1,27 @@
|
|||||||
import type { UpdateUserInput } from "@minikura/db";
|
|
||||||
import { Elysia } from "elysia";
|
import { Elysia } from "elysia";
|
||||||
import { userService } from "../application/di-container";
|
import { userService } from "../application/di-container";
|
||||||
import { requireAdmin, requireAuth } from "../middleware/auth-guards";
|
import { requireAdmin } from "../middleware/auth-guards";
|
||||||
|
import { updateSuspensionSchema, updateUserSchema } from "../schemas/user.schema";
|
||||||
|
|
||||||
export const userRoutes = new Elysia({ prefix: "/users" })
|
export const userRoutes = new Elysia({ prefix: "/users" })
|
||||||
.use(requireAdmin)
|
.use(requireAdmin)
|
||||||
.get("/", async () => {
|
.get("/", async () => {
|
||||||
const users = await userService.getAllUsers();
|
return await userService.getAllUsers();
|
||||||
return users;
|
|
||||||
})
|
})
|
||||||
|
|
||||||
.use(requireAuth)
|
|
||||||
.get("/:id", async ({ params }) => {
|
.get("/:id", async ({ params }) => {
|
||||||
const foundUser = await userService.getUserById(params.id);
|
return await userService.getUserById(params.id);
|
||||||
return foundUser;
|
|
||||||
})
|
})
|
||||||
|
|
||||||
.use(requireAdmin)
|
|
||||||
.patch("/:id", async ({ params, body }) => {
|
.patch("/:id", async ({ params, body }) => {
|
||||||
const input = body as UpdateUserInput;
|
const input = updateUserSchema.parse(body);
|
||||||
const updatedUser = await userService.updateUser(params.id, input);
|
return await userService.updateUser(params.id, input);
|
||||||
return updatedUser;
|
})
|
||||||
|
.patch("/:id/suspension", async ({ params, body }) => {
|
||||||
|
const payload = updateSuspensionSchema.parse(body);
|
||||||
|
return await userService.updateSuspension(params.id, {
|
||||||
|
isSuspended: payload.isSuspended,
|
||||||
|
suspendedUntil: payload.suspendedUntil ? new Date(payload.suspendedUntil) : null,
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
.use(requireAuth)
|
|
||||||
.delete("/:id", async ({ params, user }) => {
|
.delete("/:id", async ({ params, user }) => {
|
||||||
await userService.deleteUser(user.id, params.id);
|
await userService.deleteUser(user.id, params.id);
|
||||||
return { success: true };
|
return { success: true };
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import type { ConnectionInfo, K8sNodeSummary, PodInfo } from "@minikura/api";
|
import type { ConnectionInfo, CustomResourceSummary, K8sNodeSummary, PodInfo } from "@minikura/api";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { api } from "@/lib/api-client";
|
import { api } from "@/lib/api-client";
|
||||||
import { getReverseProxyApi } from "@/lib/api-helpers";
|
import { getReverseProxyApi } from "@/lib/api-helpers";
|
||||||
@@ -119,6 +119,20 @@ export function useTopologyData() {
|
|||||||
nodeMetrics = nodeMetricsRes.data || { items: [] };
|
nodeMetrics = nodeMetricsRes.data || { items: [] };
|
||||||
} catch (_err) {}
|
} catch (_err) {}
|
||||||
|
|
||||||
|
const proxyBackends = new Map<string, string[]>();
|
||||||
|
try {
|
||||||
|
const crResponse = await api.api.k8s["reverse-proxy-servers"].get();
|
||||||
|
for (const cr of (crResponse.data as CustomResourceSummary[]) || []) {
|
||||||
|
const backends = cr.status?.backends;
|
||||||
|
if (cr.name && Array.isArray(backends)) {
|
||||||
|
proxyBackends.set(
|
||||||
|
cr.name,
|
||||||
|
backends.filter((id): id is string => typeof id === "string")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_err) {}
|
||||||
|
|
||||||
const topologyGraph = buildTopologyGraph({
|
const topologyGraph = buildTopologyGraph({
|
||||||
servers: normalServers,
|
servers: normalServers,
|
||||||
proxies: reverseProxies,
|
proxies: reverseProxies,
|
||||||
@@ -127,6 +141,7 @@ export function useTopologyData() {
|
|||||||
k8sNodes,
|
k8sNodes,
|
||||||
serverConnections: serverConnectionMap,
|
serverConnections: serverConnectionMap,
|
||||||
proxyConnections: proxyConnectionMap,
|
proxyConnections: proxyConnectionMap,
|
||||||
|
proxyBackends,
|
||||||
podMetrics,
|
podMetrics,
|
||||||
nodeMetrics,
|
nodeMetrics,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -59,16 +59,23 @@ interface BuildEnhancedGraphInput {
|
|||||||
k8sNodes: K8sNodeSummary[];
|
k8sNodes: K8sNodeSummary[];
|
||||||
serverConnections?: Map<string, ConnectionInfo | null>;
|
serverConnections?: Map<string, ConnectionInfo | null>;
|
||||||
proxyConnections?: Map<string, ConnectionInfo | null>;
|
proxyConnections?: Map<string, ConnectionInfo | null>;
|
||||||
|
proxyBackends?: Map<string, string[]>;
|
||||||
podMetrics?: any;
|
podMetrics?: any;
|
||||||
nodeMetrics?: any;
|
nodeMetrics?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseProxyServerConnections(
|
function parseProxyServerConnections(
|
||||||
_proxy: ReverseProxyServer,
|
proxy: ReverseProxyServer,
|
||||||
allServers: NormalServer[]
|
allServers: NormalServer[],
|
||||||
|
backendsByProxyId?: Map<string, string[]>
|
||||||
): string[] {
|
): string[] {
|
||||||
|
const backends = backendsByProxyId?.get(proxy.id);
|
||||||
|
if (!backends) {
|
||||||
return allServers.map((s) => s.id);
|
return allServers.map((s) => s.id);
|
||||||
}
|
}
|
||||||
|
const known = new Set(allServers.map((s) => s.id));
|
||||||
|
return backends.filter((id) => known.has(id));
|
||||||
|
}
|
||||||
|
|
||||||
export function buildTopologyGraph(input: BuildEnhancedGraphInput): TopologyGraph {
|
export function buildTopologyGraph(input: BuildEnhancedGraphInput): TopologyGraph {
|
||||||
const {
|
const {
|
||||||
@@ -79,6 +86,7 @@ export function buildTopologyGraph(input: BuildEnhancedGraphInput): TopologyGrap
|
|||||||
k8sNodes,
|
k8sNodes,
|
||||||
serverConnections,
|
serverConnections,
|
||||||
proxyConnections,
|
proxyConnections,
|
||||||
|
proxyBackends,
|
||||||
podMetrics,
|
podMetrics,
|
||||||
nodeMetrics,
|
nodeMetrics,
|
||||||
} = input;
|
} = input;
|
||||||
@@ -103,7 +111,7 @@ export function buildTopologyGraph(input: BuildEnhancedGraphInput): TopologyGrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const proxy of proxies) {
|
for (const proxy of proxies) {
|
||||||
const connectedServerIds = parseProxyServerConnections(proxy, servers);
|
const connectedServerIds = parseProxyServerConnections(proxy, servers, proxyBackends);
|
||||||
proxyToServers.set(proxy.id, connectedServerIds);
|
proxyToServers.set(proxy.id, connectedServerIds);
|
||||||
|
|
||||||
for (const serverId of connectedServerIds) {
|
for (const serverId of connectedServerIds) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"@hookform/resolvers": "^5.7.1",
|
"@hookform/resolvers": "^5.7.1",
|
||||||
"@minikura/api": "workspace:*",
|
"@minikura/api": "workspace:*",
|
||||||
"@minikura/backend": "workspace:*",
|
"@minikura/backend": "workspace:*",
|
||||||
|
"@minikura/shared": "workspace:*",
|
||||||
"@radix-ui/react-accordion": "^1.2.20",
|
"@radix-ui/react-accordion": "^1.2.20",
|
||||||
"@radix-ui/react-avatar": "^1.2.6",
|
"@radix-ui/react-avatar": "^1.2.6",
|
||||||
"@radix-ui/react-checkbox": "^1.3.11",
|
"@radix-ui/react-checkbox": "^1.3.11",
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
"@hookform/resolvers": "^5.7.1",
|
"@hookform/resolvers": "^5.7.1",
|
||||||
"@minikura/api": "workspace:*",
|
"@minikura/api": "workspace:*",
|
||||||
"@minikura/backend": "workspace:*",
|
"@minikura/backend": "workspace:*",
|
||||||
|
"@minikura/shared": "workspace:*",
|
||||||
"@radix-ui/react-accordion": "^1.2.20",
|
"@radix-ui/react-accordion": "^1.2.20",
|
||||||
"@radix-ui/react-avatar": "^1.2.6",
|
"@radix-ui/react-avatar": "^1.2.6",
|
||||||
"@radix-ui/react-checkbox": "^1.3.11",
|
"@radix-ui/react-checkbox": "^1.3.11",
|
||||||
@@ -97,6 +98,9 @@
|
|||||||
"typescript": "^7.0.2",
|
"typescript": "^7.0.2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"operator": {
|
||||||
|
"name": "@minikura/operator",
|
||||||
|
},
|
||||||
"packages/api": {
|
"packages/api": {
|
||||||
"name": "@minikura/api",
|
"name": "@minikura/api",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -333,6 +337,8 @@
|
|||||||
|
|
||||||
"@minikura/db": ["@minikura/db@workspace:packages/db"],
|
"@minikura/db": ["@minikura/db@workspace:packages/db"],
|
||||||
|
|
||||||
|
"@minikura/operator": ["@minikura/operator@workspace:operator"],
|
||||||
|
|
||||||
"@minikura/shared": ["@minikura/shared@workspace:packages/shared"],
|
"@minikura/shared": ["@minikura/shared@workspace:packages/shared"],
|
||||||
|
|
||||||
"@minikura/web": ["@minikura/web@workspace:apps/web"],
|
"@minikura/web": ["@minikura/web@workspace:apps/web"],
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class Main @Inject constructor(private val logger: Logger, private val server: P
|
|||||||
private val client = OkHttpClient()
|
private val client = OkHttpClient()
|
||||||
private val apiKey: String = System.getenv("MINIKURA_API_KEY") ?: ""
|
private val apiKey: String = System.getenv("MINIKURA_API_KEY") ?: ""
|
||||||
private val apiUrl: String = System.getenv("MINIKURA_API_URL") ?: "http://localhost:3000/api"
|
private val apiUrl: String = System.getenv("MINIKURA_API_URL") ?: "http://localhost:3000/api"
|
||||||
private val websocketUrl: String = System.getenv("MINIKURA_WEBSOCKET_URL") ?: "ws://localhost:3000/ws?apiKey=$apiKey"
|
private val websocketUrl: String = System.getenv("MINIKURA_WEBSOCKET_URL") ?: "ws://localhost:3000/api/servers/ws?apiKey=$apiKey"
|
||||||
private var acceptingTransfers = AtomicBoolean(false)
|
private var acceptingTransfers = AtomicBoolean(false)
|
||||||
private val redisBungeeApi = RedisBungeeAPI.getRedisBungeeApi()
|
private val redisBungeeApi = RedisBungeeAPI.getRedisBungeeApi()
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ class Main @Inject constructor(private val logger: Logger, private val server: P
|
|||||||
|
|
||||||
private fun fetchReverseProxyServers() {
|
private fun fetchReverseProxyServers() {
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url("$apiUrl/reverse_proxy_servers")
|
.url("$apiUrl/plugin/reverse-proxy")
|
||||||
.header("Authorization", "Bearer $apiKey")
|
.header("Authorization", "Bearer $apiKey")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ class Main @Inject constructor(private val logger: Logger, private val server: P
|
|||||||
private fun fetchServers() {
|
private fun fetchServers() {
|
||||||
server.allServers.forEach { server.unregisterServer(it.serverInfo) }
|
server.allServers.forEach { server.unregisterServer(it.serverInfo) }
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url("$apiUrl/servers")
|
.url("$apiUrl/plugin/servers")
|
||||||
.header("Authorization", "Bearer $apiKey")
|
.header("Authorization", "Bearer $apiKey")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
|||||||
+1
-8
@@ -30,15 +30,8 @@ class MinikuraWebSocketClient(private val plugin: Main, private val logger: Logg
|
|||||||
"test" -> {
|
"test" -> {
|
||||||
logger.info("API Call detected: endpoint=$endpoint, timestamp=$timestamp")
|
logger.info("API Call detected: endpoint=$endpoint, timestamp=$timestamp")
|
||||||
|
|
||||||
when (endpoint) {
|
|
||||||
"/servers" -> {
|
|
||||||
logger.info("dawdawdawdawd")
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
logger.info("API endpoint $endpoint was accessed")
|
logger.info("API endpoint $endpoint was accessed")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
"SERVER_CHANGE" -> {
|
"SERVER_CHANGE" -> {
|
||||||
val action = jsonObject.get("action")?.asString
|
val action = jsonObject.get("action")?.asString
|
||||||
val serverType = jsonObject.get("serverType")?.asString
|
val serverType = jsonObject.get("serverType")?.asString
|
||||||
@@ -46,7 +39,7 @@ class MinikuraWebSocketClient(private val plugin: Main, private val logger: Logg
|
|||||||
|
|
||||||
logger.info("Server change detected: action=$action, serverType=$serverType, serverId=$serverId")
|
logger.info("Server change detected: action=$action, serverType=$serverType, serverId=$serverId")
|
||||||
|
|
||||||
when (action) {
|
when (action?.uppercase()) {
|
||||||
"CREATE" -> {
|
"CREATE" -> {
|
||||||
logger.info("Server '$serverId' was created")
|
logger.info("Server '$serverId' was created")
|
||||||
executeRefreshCommand()
|
executeRefreshCommand()
|
||||||
|
|||||||
Reference in New Issue
Block a user