Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip #1

Merged
merged 27 commits into from
Nov 11, 2023
Merged
Prev Previous commit
Next Next commit
wip
  • Loading branch information
louislam committed Oct 29, 2023
commit e67d08b7b3abfdf6e1662a93c89a074e75140b26
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ A fancy, easy-to-use and reactive docker stack (`docker-compose.yml`) manager.
- Interactive web terminal for containers and any docker commands
- Reactive - Everything is just responsive. Progress and terminal output are in real-time
- Easy-to-use & fancy UI - If you love Uptime Kuma's UI, you will love this too
- Build on top of [Compose V2](https://docs.docker.com/compose/migrate/), as known as `compose.yaml` and `docker compose`

## Installation

Expand All @@ -30,4 +31,6 @@ If you love this project, please consider giving this project a ⭐.
- Container stats
- Get app icons
- Switch Docker context
- Support Dockerfile and build
- Zero-config private docker registry
- Support Docker swarm
53 changes: 43 additions & 10 deletions backend/dockge-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import expressStaticGzip from "express-static-gzip";
import path from "path";
import { TerminalSocketHandler } from "./socket-handlers/terminal-socket-handler";
import { Stack } from "./stack";
import { Cron } from "croner";
import childProcess from "child_process";

export class DockgeServer {
app : Express;
Expand Down Expand Up @@ -248,6 +250,15 @@ export class DockgeServer {
} else {
log.info("server", `Listening on ${this.config.port}`);
}

// Run every 5 seconds
const job = Cron("*/2 * * * * *", {
protect: true, // Enabled over-run protection.
}, () => {
log.debug("server", "Cron job running");
this.sendStackList(true);
});

});
}

Expand Down Expand Up @@ -412,18 +423,40 @@ export class DockgeServer {
return jwtSecretBean;
}

sendStackList(socket : DockgeSocket) {
let room = socket.userID.toString();
let stackList = Stack.getStackList(this);
let list = {};
sendStackList(useCache = false) {
let stackList = Stack.getStackList(this, useCache);
let roomList = this.io.sockets.adapter.rooms.keys();
for (let room of roomList) {
// Check if the room is a number (user id)
if (Number(room)) {
this.io.to(room).emit("stackList", {
ok: true,
stackList: Object.fromEntries(stackList),
});
}
}
}

sendStackStatusList() {
let statusList = Stack.getStatusList();

for (let stack of stackList) {
list[stack.name] = stack.toSimpleJSON();
let roomList = this.io.sockets.adapter.rooms.keys();

for (let room of roomList) {
// Check if the room is a number (user id)
if (Number(room)) {
log.debug("server", "Send stack status list to room " + room);
this.io.to(room).emit("stackStatusList", {
ok: true,
stackStatusList: Object.fromEntries(statusList),
});
} else {
log.debug("server", "Skip sending stack status list to room " + room);
}
}
}

this.io.to(room).emit("stackList", {
ok: true,
stackList: list,
});
get stackDirFullPath() {
return path.resolve(this.stacksDir);
}
}
41 changes: 28 additions & 13 deletions backend/socket-handlers/docker-socket-handler.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,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,
isDev,
PROGRESS_TERMINAL_ROWS
} from "../util-common";
import { Terminal } from "../terminal";
import { Stack } from "../stack";

export class DockerSocketHandler extends SocketHandler {
Expand All @@ -23,6 +11,7 @@ export class DockerSocketHandler extends SocketHandler {
checkLogin(socket);
const stack = this.saveStack(socket, server, name, composeYAML, isAdd);
await stack.deploy(socket);
server.sendStackList();
callback({
ok: true,
});
Expand All @@ -39,7 +28,33 @@ export class DockerSocketHandler extends SocketHandler {
ok: true,
"msg": "Saved"
});
server.sendStackList(socket);
server.sendStackList();
} catch (e) {
callbackError(e, callback);
}
});

socket.on("deleteStack", async (name : unknown, callback) => {
try {
checkLogin(socket);
if (typeof(name) !== "string") {
throw new ValidationError("Name must be a string");
}
const stack = Stack.getStack(server, name);

try {
await stack.delete(socket);
} catch (e) {
server.sendStackList();
throw e;
}

server.sendStackList();
callback({
ok: true,
msg: "Deleted"
});

} catch (e) {
callbackError(e, callback);
}
Expand Down
38 changes: 34 additions & 4 deletions backend/socket-handlers/terminal-socket-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ import { log } from "../log";
import yaml from "yaml";
import path from "path";
import fs from "fs";
import { allowedCommandList, allowedRawKeys, isDev } from "../util-common";
import { Terminal } from "../terminal";
import {
allowedCommandList,
allowedRawKeys,
getComposeTerminalName,
isDev,
PROGRESS_TERMINAL_ROWS
} from "../util-common";
import { MainTerminal, Terminal } from "../terminal";

export class TerminalSocketHandler extends SocketHandler {
create(socket : DockgeSocket, server : DockgeServer) {
Expand Down Expand Up @@ -57,12 +63,36 @@ export class TerminalSocketHandler extends SocketHandler {
});

// Create Terminal
socket.on("terminalCreate", async (terminalName : unknown, callback : unknown) => {
socket.on("mainTerminal", async (terminalName : unknown, callback) => {
try {
checkLogin(socket);
if (typeof(terminalName) !== "string") {
throw new ValidationError("Terminal name must be a string.");
}

log.debug("deployStack", "Terminal name: " + terminalName);

let terminal = Terminal.getTerminal(terminalName);

if (!terminal) {
terminal = new MainTerminal(server, terminalName);
terminal.rows = 50;
log.debug("deployStack", "Terminal created");
}

terminal.join(socket);
terminal.start();

callback({
ok: true,
});
} catch (e) {
callbackError(e, callback);
}
});

// Join Terminal
socket.on("terminalJoin", async (terminalName : unknown, callback : unknown) => {
socket.on("terminalJoin", async (terminalName : unknown, callback) => {
if (typeof(callback) !== "function") {
log.debug("console", "Callback is not a function.");
return;
Expand Down
Loading