mirror of
https://github.com/louislam/dockge.git
synced 2024-11-23 19:34:04 +00:00
WIP
This commit is contained in:
parent
37f261480a
commit
7d91c8d037
9 changed files with 153 additions and 14 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -107,5 +107,6 @@
|
|||
"agentOffline": "Offline",
|
||||
"connecting": "Connecting",
|
||||
"connect": "Connect",
|
||||
"addAgent": "Add Agent"
|
||||
"addAgent": "Add Agent",
|
||||
"agentAddedSuccessfully": "Agent added successfully."
|
||||
}
|
||||
|
|
|
@ -259,6 +259,10 @@ export default defineComponent({
|
|||
|
||||
socket.on("agentStatus", (res) => {
|
||||
this.agentStatusList[res.endpoint] = res.status;
|
||||
|
||||
if (res.msg) {
|
||||
this.toastError(res.msg);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("agentList", (res) => {
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
<span v-if="endpoint === ''">{{ $t("currentEndpoint") }}</span>
|
||||
<span v-else>{{ endpoint }}</span>
|
||||
|
||||
<!-- Remove Button -->
|
||||
<font-awesome-icon v-if="endpoint !== ''" class="ms-2 remove-agent" icon="trash" @click="removeAgent(agent.url)" />
|
||||
</div>
|
||||
|
||||
|
@ -74,7 +75,10 @@
|
|||
<input id="password" v-model="agent.password" type="password" class="form-control" required autocomplete="new-password">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-normal">{{ $t("connect") }}</button>
|
||||
<button type="submit" class="btn btn-primary" :disabled="connectingAgent">
|
||||
<template v-if="connectingAgent">{{ $t("connecting") }}</template>
|
||||
<template v-else>{{ $t("connect") }}</template>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -110,6 +114,7 @@ export default {
|
|||
displayedRecords: [],
|
||||
dockerRunCommand: "",
|
||||
showAgentForm: false,
|
||||
connectingAgent: false,
|
||||
agent: {
|
||||
url: "http://",
|
||||
username: "",
|
||||
|
@ -156,14 +161,16 @@ export default {
|
|||
methods: {
|
||||
|
||||
addAgent() {
|
||||
this.connectingAgent = true;
|
||||
this.$root.getSocket().emit("addAgent", this.agent, (res) => {
|
||||
if (res.ok) {
|
||||
this.$root.toastRes(res);
|
||||
|
||||
if (res.ok) {
|
||||
this.showAgentForm = false;
|
||||
}
|
||||
});
|
||||
|
||||
this.showAgentForm = false;
|
||||
this.connectingAgent = false;
|
||||
});
|
||||
},
|
||||
|
||||
removeAgent(url) {
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"mysql2": "~3.6.5",
|
||||
"promisify-child-process": "~4.1.2",
|
||||
"redbean-node": "~0.3.3",
|
||||
"semver": "^7.5.4",
|
||||
"socket.io": "~4.7.2",
|
||||
"socket.io-client": "~4.7.2",
|
||||
"timezones-list": "~3.0.2",
|
||||
|
@ -66,6 +67,7 @@
|
|||
"@types/command-exists": "~1.2.3",
|
||||
"@types/express": "~4.17.21",
|
||||
"@types/jsonwebtoken": "~9.0.5",
|
||||
"@types/semver": "^7.5.6",
|
||||
"@typescript-eslint/eslint-plugin": "~6.8.0",
|
||||
"@typescript-eslint/parser": "~6.8.0",
|
||||
"@vitejs/plugin-vue": "~4.5.2",
|
||||
|
|
|
@ -68,6 +68,9 @@ dependencies:
|
|||
redbean-node:
|
||||
specifier: ~0.3.3
|
||||
version: 0.3.3(mysql2@3.6.5)
|
||||
semver:
|
||||
specifier: ^7.5.4
|
||||
version: 7.5.4
|
||||
socket.io:
|
||||
specifier: ~4.7.2
|
||||
version: 4.7.2
|
||||
|
@ -124,6 +127,9 @@ devDependencies:
|
|||
'@types/jsonwebtoken':
|
||||
specifier: ~9.0.5
|
||||
version: 9.0.5
|
||||
'@types/semver':
|
||||
specifier: ^7.5.6
|
||||
version: 7.5.6
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ~6.8.0
|
||||
version: 6.8.0(@typescript-eslint/parser@6.8.0)(eslint@8.50.0)(typescript@5.2.2)
|
||||
|
|
Loading…
Reference in a new issue