WIP
This commit is contained in:
parent
a0fca4df4d
commit
49fb055da4
6 changed files with 118 additions and 13 deletions
85
backend/dockge-instance-manager.ts
Normal file
85
backend/dockge-instance-manager.ts
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
8
pnpm-lock.yaml
generated
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue