This commit is contained in:
Louis Lam
2023-12-24 22:01:17 +08:00
parent 37f261480a
commit 7d91c8d037
9 changed files with 153 additions and 14 deletions

View File

@@ -2,7 +2,9 @@ import { DockgeSocket } from "./util-server";
import { io, Socket as SocketClient } from "socket.io-client";
import { log } from "./log";
import { Agent } from "./models/agent";
import { LooseObject } from "../common/util-common";
import { isDev, LooseObject } from "../common/util-common";
import semver from "semver";
import { R } from "redbean-node";
/**
* Dockge Instance Manager
@@ -16,6 +18,74 @@ export class AgentManager {
this.socket = socket;
}
test(url : string, username : string, password : string) : Promise<void> {
return new Promise((resolve, reject) => {
let obj = new URL(url);
let endpoint = obj.host;
if (!endpoint) {
reject(new Error("Invalid Dockge URL"));
}
if (this.instanceSocketList[endpoint]) {
reject(new Error("The Dockge URL already exists"));
}
let client = io(url, {
reconnection: false,
extraHeaders: {
endpoint,
}
});
client.on("connect", () => {
client.emit("login", {
username: username,
password: password,
}, (res : LooseObject) => {
if (res.ok) {
resolve();
} else {
reject(new Error(res.msg));
}
client.disconnect();
});
});
client.on("connect_error", (err) => {
if (err.message === "xhr poll error") {
reject(new Error("Unable to connect to the Dockge instance"));
} else {
reject(err);
}
client.disconnect();
});
});
}
/**
*
* @param url
* @param username
* @param password
*/
async add(url : string, username : string, password : string) : Promise<Agent> {
let bean = R.dispense("agent") as Agent;
bean.url = url;
bean.username = username;
bean.password = password;
await R.store(bean);
return bean;
}
/**
*
* @param endpoint
*/
remove(endpoint : string) {
}
connect(url : string, username : string, password : string) {
let obj = new URL(url);
let endpoint = obj.host;
@@ -48,7 +118,7 @@ export class AgentManager {
client.emit("login", {
username: username,
password: password,
}, (res) => {
}, (res : LooseObject) => {
if (res.ok) {
log.info("agent-manager", "Logged in to the socket server: " + endpoint);
this.socket.emit("agentStatus", {
@@ -65,9 +135,9 @@ export class AgentManager {
});
});
client.on("error", (err) => {
client.on("connect_error", (err) => {
log.error("agent-manager", "Error from the socket server: " + endpoint);
log.error("agent-manager", err);
log.debug("agent-manager", err);
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "offline",
@@ -87,6 +157,20 @@ export class AgentManager {
this.socket.emit("agent", ...args);
});
client.on("info", (res) => {
log.debug("agent-manager", res);
// Disconnect if the version is lower than 1.4.0
if (!isDev && semver.satisfies(res.version, "< 1.4.0")) {
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "offline",
msg: `${endpoint}: Unsupported version: ` + res.version,
});
client.disconnect();
}
});
this.instanceSocketList[endpoint] = client;
}

View File

@@ -251,7 +251,7 @@ export class DockgeServer {
let obj2 = obj as LooseObject;
obj2.endpoint = dockgeSocket.endpoint;
}
this.io.to(dockgeSocket.userID + "").emit("agent", event, ...args);
dockgeSocket.emit("agent", event, ...args);
};
if (typeof(socket.request.headers.endpoint) === "string") {
@@ -601,7 +601,7 @@ export class DockgeServer {
map.set(stackName, stack.toSimpleJSON(dockgeSocket.endpoint));
}
log.debug("server", "Send stack list");
log.debug("server", "Send stack list to user: " + dockgeSocket.id + " (" + dockgeSocket.endpoint + ")");
dockgeSocket.emitAgent("stackList", {
ok: true,
stackList: Object.fromEntries(map),

View File

@@ -1,13 +1,46 @@
import { SocketHandler } from "../socket-handler.js";
import { DockgeServer } from "../dockge-server";
import { log } from "../log";
import { checkLogin, DockgeSocket } from "../util-server";
import { AgentSocket } from "../../common/agent-socket";
import { ALL_ENDPOINTS } from "../../common/util-common";
import { callbackError, checkLogin, DockgeSocket } from "../util-server";
export class ManageAgentSocketHandler extends SocketHandler {
create(socket : DockgeSocket, server : DockgeServer) {
// addAgent
socket.on("addAgent", async (data : unknown, callback : unknown) => {
try {
log.debug("manage-agent-socket-handler", "addAgent");
checkLogin(socket);
let manager = socket.instanceManager;
await manager.test(data.url, data.username, data.password);
await manager.add(data.url, data.username, data.password);
// connect to the agent
manager.connect(data.url, data.username, data.password);
manager.sendAgentList();
callback({
ok: true,
msg: "agentAddedSuccessfully",
msgi18n: true,
});
} catch (e) {
callbackError(e, callback);
}
});
// removeAgent
socket.on("removeAgent", async (data : unknown, callback : unknown) => {
try {
log.debug("manage-agent-socket-handler", "removeAgent");
checkLogin(socket);
await socket.instanceManager.remove(data.endpoint);
} catch (e) {
callbackError(e, callback);
}
});
}
}

View File

@@ -60,12 +60,14 @@ export function callbackError(error : unknown, callback : unknown) {
callback({
ok: false,
msg: error.message,
msgi18n: true,
});
} else if (error instanceof ValidationError) {
callback({
ok: false,
type: ERROR_TYPE_VALIDATION,
msg: error.message,
msgi18n: true,
});
} else {
log.debug("console", "Unknown error: " + error);