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

Container control buttons #649

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions backend/agent-socket-handlers/docker-socket-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ export class DockerSocketHandler extends AgentSocketHandler {
msgi18n: true,
}, callback);
server.sendStackList();

stack.leaveCombinedTerminal(socket);
} catch (e) {
callbackError(e, callback);
}
Expand Down Expand Up @@ -238,6 +240,68 @@ export class DockerSocketHandler extends AgentSocketHandler {
}
});

// Start a service
agentSocket.on("startService", async (stackName: unknown, serviceName: unknown, callback) => {
try {
checkLogin(socket);

if (typeof (stackName) !== "string" || typeof (serviceName) !== "string") {
throw new ValidationError("Stack name and service name must be strings");
}

const stack = await Stack.getStack(server, stackName);
await stack.startService(socket, serviceName);
stack.joinCombinedTerminal(socket); // Ensure the combined terminal is joined
callbackResult({
ok: true,
msg: "Service" + serviceName + " started"
}, callback);
server.sendStackList();
} catch (e) {
callbackError(e, callback);
}
});

// Stop a service
agentSocket.on("stopService", async (stackName: unknown, serviceName: unknown, callback) => {
try {
checkLogin(socket);

if (typeof (stackName) !== "string" || typeof (serviceName) !== "string") {
throw new ValidationError("Stack name and service name must be strings");
}

const stack = await Stack.getStack(server, stackName);
await stack.stopService(socket, serviceName);
callbackResult({
ok: true,
msg: "Service" + serviceName + " stopped"
}, callback);
server.sendStackList();
} catch (e) {
callbackError(e, callback);
}
});

agentSocket.on("restartService", async (stackName: unknown, serviceName: unknown, callback) => {
try {
checkLogin(socket);

if (typeof stackName !== "string" || typeof serviceName !== "string") {
throw new Error("Invalid stackName or serviceName");
}

const stack = await Stack.getStack(server, stackName, true);
await stack.restartService(socket, serviceName);
callbackResult({
ok: true,
msg: "Service" + serviceName + " restarted"
}, callback);
} catch (e) {
callbackError(e, callback);
}
});

// getExternalNetworkList
agentSocket.on("getDockerNetworkList", async (callback) => {
try {
Expand Down
30 changes: 30 additions & 0 deletions backend/stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,4 +530,34 @@ export class Stack {
}

}

async startService(socket: DockgeSocket, serviceName: string) {
const terminalName = getComposeTerminalName(socket.endpoint, this.name);
const exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", ["compose", "up", "-d", serviceName], this.path);
if (exitCode !== 0) {
throw new Error(`Failed to start service ${serviceName}, please check logs for more information.`);
}

return exitCode;
}

async stopService(socket: DockgeSocket, serviceName: string): Promise<number> {
const terminalName = getComposeTerminalName(socket.endpoint, this.name);
const exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", ["compose", "stop", serviceName], this.path);
if (exitCode !== 0) {
throw new Error(`Failed to stop service ${serviceName}, please check logs for more information.`);
}

return exitCode;
}

async restartService(socket: DockgeSocket, serviceName: string): Promise<number> {
const terminalName = getComposeTerminalName(socket.endpoint, this.name);
const exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", ["compose", "restart", serviceName], this.path);
if (exitCode !== 0) {
throw new Error(`Failed to restart service ${serviceName}, please check logs for more information.`);
}

return exitCode;
}
}
35 changes: 33 additions & 2 deletions frontend/src/components/Container.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="shadow-box big-padding mb-3 container">
<div class="row">
<div class="col-7">
<div class="col-5">
<h4>{{ name }}</h4>
<div class="image mb-2">
<span class="me-1">{{ imageName }}:</span><span class="tag">{{ imageTag }}</span>
Expand All @@ -14,12 +14,33 @@
</a>
</div>
</div>
<div class="col-5">
<div class="col-7">
<div class="function">
<router-link v-if="!isEditMode" class="btn btn-normal" :to="terminalRouteLink" disabled="">
<font-awesome-icon icon="terminal" />
Bash
</router-link>
<button v-if="status !== 'running' && status !== 'healthy'"
class="btn btn-primary me-2"
:disabled="processing"
@click="startService">
<font-awesome-icon icon="play" class="me-1" />
Start
</button>
<button v-if="status === 'running' || status === 'healthy' || status === 'unhealthy'"
class="btn btn-danger me-2"
:disabled="processing"
@click="stopService">
<font-awesome-icon icon="stop" class="me-1" />
Stop
</button>
<button v-if="status === 'running' || status === 'healthy' || status === 'unhealthy'"
class="btn btn-warning me-2"
:disabled="processing"
@click="restartService">
<font-awesome-icon icon="sync" class="me-1" />
Restart
</button>
</div>
</div>
</div>
Expand Down Expand Up @@ -284,6 +305,16 @@ export default defineComponent({
remove() {
delete this.jsonObject.services[this.name];
},
startService() {
this.$emit("start-service", this.name);
},
stopService() {
this.$emit("stop-service", this.name);
},
restartService() {
this.$emit("restart-service", this.name);
}

}
});
</script>
Expand Down
42 changes: 42 additions & 0 deletions frontend/src/pages/Compose.vue
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@
:is-edit-mode="isEditMode"
:first="name === Object.keys(jsonConfig.services)[0]"
:status="serviceStatusList[name]"
:processing="processing"
@start-service="startService"
@stop-service="stopService"
@restart-service="restartService"
/>
</div>

Expand Down Expand Up @@ -786,6 +790,44 @@ export default {
this.stack.name = this.stack?.name?.toLowerCase();
},

startService(serviceName) {
this.processing = true;

this.$root.emitAgent(this.endpoint, "startService", this.stack.name, serviceName, (res) => {
this.processing = false;
this.$root.toastRes(res);

if (res.ok) {
this.requestServiceStatus(); // Refresh service status
}
});
},

stopService(serviceName) {
this.processing = true;

this.$root.emitAgent(this.endpoint, "stopService", this.stack.name, serviceName, (res) => {
this.processing = false;
this.$root.toastRes(res);

if (res.ok) {
this.requestServiceStatus(); // Refresh service status
}
});
},

restartService(serviceName) {
this.processing = true;

this.$root.emitAgent(this.endpoint, "restartService", this.stack.name, serviceName, (res) => {
this.processing = false;
this.$root.toastRes(res);

if (res.ok) {
this.requestServiceStatus(); // Refresh service status
}
});
},
}
};
</script>
Expand Down
Loading