This commit is contained in:
Louis Lam 2023-12-25 01:52:00 +08:00
parent 7d91c8d037
commit 0c32171acc
7 changed files with 324 additions and 271 deletions

View file

@ -12,7 +12,7 @@ import { R } from "redbean-node";
export class AgentManager { export class AgentManager {
protected socket : DockgeSocket; protected socket : DockgeSocket;
protected instanceSocketList : Record<string, SocketClient> = {}; protected agentSocketList : Record<string, SocketClient> = {};
constructor(socket: DockgeSocket) { constructor(socket: DockgeSocket) {
this.socket = socket; this.socket = socket;
@ -27,7 +27,7 @@ export class AgentManager {
reject(new Error("Invalid Dockge URL")); reject(new Error("Invalid Dockge URL"));
} }
if (this.instanceSocketList[endpoint]) { if (this.agentSocketList[endpoint]) {
reject(new Error("The Dockge URL already exists")); reject(new Error("The Dockge URL already exists"));
} }
@ -80,10 +80,20 @@ export class AgentManager {
/** /**
* *
* @param endpoint * @param url
*/ */
remove(endpoint : string) { async remove(url : string) {
let bean = await R.findOne("agent", " url = ? ", [
url,
]);
if (bean) {
await R.trash(bean);
let endpoint = bean.endpoint;
delete this.agentSocketList[endpoint];
} else {
throw new Error("Agent not found");
}
} }
connect(url : string, username : string, password : string) { connect(url : string, username : string, password : string) {
@ -100,7 +110,7 @@ export class AgentManager {
return; return;
} }
if (this.instanceSocketList[endpoint]) { if (this.agentSocketList[endpoint]) {
log.debug("agent-manager", "Already connected to the socket server: " + endpoint); log.debug("agent-manager", "Already connected to the socket server: " + endpoint);
return; return;
} }
@ -171,11 +181,11 @@ export class AgentManager {
} }
}); });
this.instanceSocketList[endpoint] = client; this.agentSocketList[endpoint] = client;
} }
disconnect(endpoint : string) { disconnect(endpoint : string) {
let client = this.instanceSocketList[endpoint]; let client = this.agentSocketList[endpoint];
client?.disconnect(); client?.disconnect();
} }
@ -198,14 +208,14 @@ export class AgentManager {
} }
disconnectAll() { disconnectAll() {
for (let endpoint in this.instanceSocketList) { for (let endpoint in this.agentSocketList) {
this.disconnect(endpoint); this.disconnect(endpoint);
} }
} }
emitToEndpoint(endpoint: string, eventName: string, ...args : unknown[]) { emitToEndpoint(endpoint: string, eventName: string, ...args : unknown[]) {
log.debug("agent-manager", "Emitting event to endpoint: " + endpoint); log.debug("agent-manager", "Emitting event to endpoint: " + endpoint);
let client = this.instanceSocketList[endpoint]; let client = this.agentSocketList[endpoint];
if (!client) { if (!client) {
log.error("agent-manager", "Socket client not found for endpoint: " + endpoint); log.error("agent-manager", "Socket client not found for endpoint: " + endpoint);
throw new Error("Socket client not found for endpoint: " + endpoint); throw new Error("Socket client not found for endpoint: " + endpoint);
@ -215,7 +225,7 @@ export class AgentManager {
emitToAllEndpoints(eventName: string, ...args : unknown[]) { emitToAllEndpoints(eventName: string, ...args : unknown[]) {
log.debug("agent-manager", "Emitting event to all endpoints"); log.debug("agent-manager", "Emitting event to all endpoints");
for (let endpoint in this.instanceSocketList) { for (let endpoint in this.agentSocketList) {
this.emitToEndpoint(endpoint, eventName, ...args); this.emitToEndpoint(endpoint, eventName, ...args);
} }
} }

View file

@ -663,10 +663,10 @@ export class DockgeServer {
* @param {string} userID * @param {string} userID
* @param {string?} currentSocketID * @param {string?} currentSocketID
*/ */
disconnectAllSocketClients(userID: number, currentSocketID? : string) { disconnectAllSocketClients(userID: number | undefined, currentSocketID? : string) {
for (const rawSocket of this.io.sockets.sockets.values()) { for (const rawSocket of this.io.sockets.sockets.values()) {
let socket = rawSocket as DockgeSocket; let socket = rawSocket as DockgeSocket;
if (socket.userID === userID && socket.id !== currentSocketID) { if ((!userID || socket.userID === userID) && socket.id !== currentSocketID) {
try { try {
socket.emit("refresh"); socket.emit("refresh");
socket.disconnect(); socket.disconnect();

View file

@ -11,7 +11,6 @@ export class ManageAgentSocketHandler extends SocketHandler {
try { try {
log.debug("manage-agent-socket-handler", "addAgent"); log.debug("manage-agent-socket-handler", "addAgent");
checkLogin(socket); checkLogin(socket);
let manager = socket.instanceManager; let manager = socket.instanceManager;
await manager.test(data.url, data.username, data.password); await manager.test(data.url, data.username, data.password);
await manager.add(data.url, data.username, data.password); await manager.add(data.url, data.username, data.password);
@ -19,6 +18,9 @@ export class ManageAgentSocketHandler extends SocketHandler {
// connect to the agent // connect to the agent
manager.connect(data.url, data.username, data.password); manager.connect(data.url, data.username, data.password);
// Refresh another sockets
// It is a bit difficult to control another browser sessions to connect/disconnect agents, so force them to refresh the page will be easier.
server.disconnectAllSocketClients(undefined, socket.id);
manager.sendAgentList(); manager.sendAgentList();
callback({ callback({
@ -33,11 +35,21 @@ export class ManageAgentSocketHandler extends SocketHandler {
}); });
// removeAgent // removeAgent
socket.on("removeAgent", async (data : unknown, callback : unknown) => { socket.on("removeAgent", async (url : unknown, callback : unknown) => {
try { try {
log.debug("manage-agent-socket-handler", "removeAgent"); log.debug("manage-agent-socket-handler", "removeAgent");
checkLogin(socket); checkLogin(socket);
await socket.instanceManager.remove(data.endpoint); let manager = socket.instanceManager;
await manager.remove(url);
server.disconnectAllSocketClients(undefined, socket.id);
manager.sendAgentList();
callback({
ok: true,
msg: "agentRemovedSuccessfully",
msgi18n: true,
});
} catch (e) { } catch (e) {
callbackError(e, callback); callbackError(e, callback);
} }

View file

@ -108,5 +108,8 @@
"connecting": "Connecting", "connecting": "Connecting",
"connect": "Connect", "connect": "Connect",
"addAgent": "Add Agent", "addAgent": "Add Agent",
"agentAddedSuccessfully": "Agent added successfully." "agentAddedSuccessfully": "Agent added successfully.",
"agentRemovedSuccessfully": "Agent removed successfully.",
"removeAgent": "Remove Agent",
"removeAgentMsg": "Are you sure you want to remove this agent?"
} }

View file

@ -53,7 +53,13 @@
<span v-else>{{ endpoint }}</span> <span v-else>{{ endpoint }}</span>
<!-- Remove Button --> <!-- Remove Button -->
<font-awesome-icon v-if="endpoint !== ''" class="ms-2 remove-agent" icon="trash" @click="removeAgent(agent.url)" /> <font-awesome-icon v-if="endpoint !== ''" class="ms-2 remove-agent" icon="trash" @click="showRemoveAgentDialog[agent.url] = !showRemoveAgentDialog[agent.url]" />
<!-- Remoe Agent Dialog -->
<BModal v-model="showRemoveAgentDialog[agent.url]" :okTitle="$t('removeAgent')" okVariant="danger" @ok="removeAgent(agent.url)">
<p>{{ agent.url }}</p>
{{ $t("removeAgentMsg") }}
</BModal>
</div> </div>
<button v-if="!showAgentForm" class="btn btn-normal" @click="showAgentForm = !showAgentForm">{{ $t("addAgent") }}</button> <button v-if="!showAgentForm" class="btn btn-normal" @click="showAgentForm = !showAgentForm">{{ $t("addAgent") }}</button>
@ -114,6 +120,7 @@ export default {
displayedRecords: [], displayedRecords: [],
dockerRunCommand: "", dockerRunCommand: "",
showAgentForm: false, showAgentForm: false,
showRemoveAgentDialog: {},
connectingAgent: false, connectingAgent: false,
agent: { agent: {
url: "http://", url: "http://",
@ -167,6 +174,11 @@ export default {
if (res.ok) { if (res.ok) {
this.showAgentForm = false; this.showAgentForm = false;
this.agent = {
url: "http://",
username: "",
password: "",
};
} }
this.connectingAgent = false; this.connectingAgent = false;
@ -177,6 +189,12 @@ export default {
this.$root.getSocket().emit("removeAgent", url, (res) => { this.$root.getSocket().emit("removeAgent", url, (res) => {
if (res.ok) { if (res.ok) {
this.$root.toastRes(res); this.$root.toastRes(res);
let urlObj = new URL(url);
let endpoint = urlObj.host;
// Remove the stack list and status list of the removed agent
delete this.$root.allAgentStackList[endpoint];
} }
}); });
}, },

View file

@ -84,9 +84,9 @@
"sass": "~1.68.0", "sass": "~1.68.0",
"typescript": "~5.2.2", "typescript": "~5.2.2",
"unplugin-vue-components": "~0.25.2", "unplugin-vue-components": "~0.25.2",
"vite": "~5.0.7", "vite": "~5.0.10",
"vite-plugin-compression": "~0.5.1", "vite-plugin-compression": "~0.5.1",
"vue": "~3.3.11", "vue": "~3.3.13",
"vue-eslint-parser": "~9.3.2", "vue-eslint-parser": "~9.3.2",
"vue-i18n": "~9.5.0", "vue-i18n": "~9.5.0",
"vue-prism-editor": "2.0.0-alpha.2", "vue-prism-editor": "2.0.0-alpha.2",

File diff suppressed because it is too large Load diff