This commit is contained in:
Louis Lam 2023-11-28 17:37:59 +08:00
parent a0fca4df4d
commit 49fb055da4
6 changed files with 118 additions and 13 deletions

View file

@ -0,0 +1,85 @@
import { DockgeSocket } from "./util-server";
import { io } from "socket.io-client";
import { log } from "./log";
/**
* Dockge Instance Manager
*/
export class DockgeInstanceManager {
protected static instance: DockgeInstanceManager;
protected constructor() {
}
public static getInstance(): DockgeInstanceManager {
if (!DockgeInstanceManager.instance) {
DockgeInstanceManager.instance = new DockgeInstanceManager();
}
return DockgeInstanceManager.instance;
}
connect(socket: DockgeSocket) {
let list : Record<string, { username : string, password : string}> = {
"ws://louis-twister-pi:5001": {
username: "admin",
password: process.env.DOCKGE_PW || "",
}
};
if (Object.keys(list).length !== 0) {
log.info("INSTANCEMANAGER", "Connecting to all instance socket server(s)...");
}
for (let url in list) {
let item = list[url];
let client = io(url, {
transports: [ "websocket", "polling" ],
});
client.on("connect", () => {
log.info("INSTANCEMANAGER", "Connected to the socket server: " + url);
client.emit("login", {
username: item.username,
password: item.password,
}, (res) => {
if (res.ok) {
log.info("INSTANCEMANAGER", "Logged in to the socket server: " + url);
} else {
log.error("INSTANCEMANAGER", "Failed to login to the socket server: " + url);
}
});
});
// Catch all events
client.onAny((eventName, ...args) => {
log.debug("INSTANCEMANAGER", "Received event: " + eventName);
let proxyEventList = [
"stackList",
];
if (proxyEventList.includes(eventName)) {
// Add the socket url in the res object to determine which socket server it is from
if (args.length > 0 && typeof args[0] === "object") {
args[0].instanceURL = url;
}
socket.emit(eventName, ...args);
} else {
log.debug("INSTANCEMANAGER", "Event not in the proxy list: " + eventName);
}
});
socket.instanceSocketList[url] = client;
}
}
disconnect(socket: DockgeSocket) {
for (let url in socket.instanceSocketList) {
let client = socket.instanceSocketList[url];
client.disconnect();
}
}
}

View file

@ -31,6 +31,9 @@ import gracefulShutdown from "http-graceful-shutdown";
import User from "./models/user";
import childProcess from "child_process";
import { Terminal } from "./terminal";
import { DockgeInstanceManager } from "./dockge-instance-manager";
import "dotenv/config";
export class DockgeServer {
app : Express;
@ -65,10 +68,13 @@ export class DockgeServer {
stacksDir : string = "";
dockgeInstanceManager : DockgeInstanceManager;
/**
*
*/
constructor() {
// Catch unexpected errors here
let unexpectedErrorHandler = (error : unknown) => {
console.trace(error);
@ -184,6 +190,8 @@ export class DockgeServer {
response.send(this.indexHTML);
});
this.dockgeInstanceManager = DockgeInstanceManager.getInstance();
// Allow all CORS origins in development
let cors = undefined;
if (isDev) {
@ -200,6 +208,9 @@ export class DockgeServer {
this.io.on("connection", async (socket: Socket) => {
log.info("server", "Socket connected!");
let dockgeSocket = socket as DockgeSocket;
dockgeSocket.instanceSocketList = {};
this.sendInfo(socket, true);
if (this.needSetup) {
@ -209,7 +220,7 @@ export class DockgeServer {
// Create socket handlers
for (const socketHandler of this.socketHandlerList) {
socketHandler.create(socket as DockgeSocket, this);
socketHandler.create(dockgeSocket, this);
}
// ***************************
@ -219,12 +230,18 @@ export class DockgeServer {
log.debug("auth", "check auto login");
if (await Settings.get("disableAuth")) {
log.info("auth", "Disabled Auth: auto login to admin");
this.afterLogin(socket as DockgeSocket, await R.findOne("user") as User);
this.afterLogin(dockgeSocket, await R.findOne("user") as User);
socket.emit("autoLogin");
} else {
log.debug("auth", "need auth");
}
// Socket disconnect
socket.on("disconnect", () => {
log.info("server", "Socket disconnected!");
this.dockgeInstanceManager.disconnect(dockgeSocket);
});
});
this.io.on("disconnect", () => {
@ -249,6 +266,9 @@ export class DockgeServer {
} catch (e) {
log.error("server", e);
}
// Also connect to other dockge instances
this.dockgeInstanceManager.connect(socket);
}
/**

View file

@ -2,16 +2,6 @@ import { SocketHandler } from "../socket-handler.js";
import { DockgeServer } from "../dockge-server";
import { callbackError, checkLogin, DockgeSocket, ValidationError } from "../util-server";
import { log } from "../log";
import yaml from "yaml";
import path from "path";
import fs from "fs";
import {
allowedCommandList,
allowedRawKeys,
getComposeTerminalName, getContainerExecTerminalName,
isDev,
PROGRESS_TERMINAL_ROWS
} from "../util-common";
import { InteractiveTerminal, MainTerminal, Terminal } from "../terminal";
import { Stack } from "../stack";

View file

@ -1,6 +1,6 @@
import { Socket } from "socket.io";
import { Socket as SocketClient } from "socket.io-client";
import { Terminal } from "./terminal";
import { randomBytes } from "crypto";
import { log } from "./log";
import { ERROR_TYPE_VALIDATION } from "./util-common";
import { R } from "redbean-node";
@ -14,6 +14,7 @@ export interface JWTDecoded {
export interface DockgeSocket extends Socket {
userID: number;
consoleTerminal? : Terminal;
instanceSocketList: Record<string, SocketClient>;
}
// For command line arguments, so they are nullable

View file

@ -31,6 +31,7 @@
"composerize": "~1.4.1",
"croner": "~7.0.5",
"dayjs": "~1.11.10",
"dotenv": "^16.3.1",
"express": "~4.18.2",
"express-static-gzip": "~2.1.7",
"http-graceful-shutdown": "~3.1.13",

8
pnpm-lock.yaml generated
View file

@ -32,6 +32,9 @@ dependencies:
dayjs:
specifier: ~1.11.10
version: 1.11.10
dotenv:
specifier: ^16.3.1
version: 16.3.1
express:
specifier: ~4.18.2
version: 4.18.2
@ -2151,6 +2154,11 @@ packages:
esutils: 2.0.3
dev: true
/dotenv@16.3.1:
resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==}
engines: {node: '>=12'}
dev: false
/eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
dev: false