Skip to content

Commit 74b60c6

Browse files
committed
Closes louislam#694
1 parent d451e06 commit 74b60c6

File tree

5 files changed

+10483
-6
lines changed

5 files changed

+10483
-6
lines changed

backend/agent-socket-handlers/docker-socket-handler.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,25 @@ export class DockerSocketHandler extends AgentSocketHandler {
6767
}
6868
});
6969

70+
agentSocket.on("forceDeleteStack", async (name : unknown, callback) => {
71+
try {
72+
checkLogin(socket);
73+
if (typeof(name) !== "string") {
74+
throw new ValidationError("Name must be a string");
75+
}
76+
const stack = await Stack.getStack(server, name);
77+
await stack.forceDelete(socket);
78+
server.sendStackList();
79+
callbackResult({
80+
ok: true,
81+
msg: "Deleted",
82+
msgi18n: true,
83+
}, callback);
84+
} catch (e) {
85+
callbackError(e, callback);
86+
}
87+
});
88+
7089
agentSocket.on("getStack", async (stackName : unknown, callback) => {
7190
try {
7291
checkLogin(socket);

backend/stack.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ export class Stack {
208208

209209
async deploy(socket : DockgeSocket) : Promise<number> {
210210
const terminalName = getComposeTerminalName(socket.endpoint, this.name);
211-
let exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", [ "compose", "up", "-d", "--remove-orphans" ], this.path);
211+
let exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", ["compose", "up", "-d", "--remove-orphans"], this.path);
212212
if (exitCode !== 0) {
213213
throw new Error("Failed to deploy, please check the terminal output for more information.");
214214
}
@@ -217,9 +217,9 @@ export class Stack {
217217

218218
async delete(socket: DockgeSocket) : Promise<number> {
219219
const terminalName = getComposeTerminalName(socket.endpoint, this.name);
220-
let exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", [ "compose", "down", "--remove-orphans" ], this.path);
220+
let exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", ["compose", "down", "--remove-orphans"], this.path);
221221
if (exitCode !== 0) {
222-
throw new Error("Failed to delete, please check the terminal output for more information.");
222+
throw new Error(`Failed to delete ${this.name}, please check the terminal output for more information.`);
223223
}
224224

225225
// Remove the stack folder
@@ -231,6 +231,19 @@ export class Stack {
231231
return exitCode;
232232
}
233233

234+
async forceDelete(socket: DockgeSocket): Promise<number> {
235+
const terminalName = getComposeTerminalName(socket.endpoint, this.name);
236+
let exitCode = await Terminal.exec(this.server, socket, terminalName, "docker", ["compose", "down", "-v", "--remove-orphans"], this.path);
237+
238+
// Remove the stack folder
239+
await fsAsync.rm(this.path, {
240+
recursive: true,
241+
force: true
242+
});
243+
244+
return exitCode;
245+
}
246+
234247
async updateStatus() {
235248
let statusList = await Stack.getStatusList();
236249
let status = statusList.get(this.name);

frontend/src/lang/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"stackName": "Stack Name",
1616
"deployStack": "Deploy",
1717
"deleteStack": "Delete",
18+
"forceDeleteStack": "Force Delete",
1819
"stopStack": "Stop",
1920
"restartStack": "Restart",
2021
"updateStack": "Update",
@@ -25,6 +26,7 @@
2526
"saveStackDraft": "Save",
2627
"notAvailableShort": "N/A",
2728
"deleteStackMsg": "Are you sure you want to delete this stack?",
29+
"forceDeleteStackMsg": "Force deleting may leave behind some files or configuration. Are you sure you want to force delete this stack?",
2830
"stackNotManagedByDockgeMsg": "This stack is not managed by Dockge.",
2931
"primaryHostname": "Primary Hostname",
3032
"general": "General",

frontend/src/pages/Compose.vue

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<transition name="slide-fade" appear>
33
<div>
4-
<h1 v-if="isAdd" class="mb-3">{{$t("compose")}}</h1>
4+
<h1 v-if="isAdd" class="mb-3">{{ $t("compose") }}</h1>
55
<h1 v-else class="mb-3">
66
<Uptime :stack="globalStack" :pill="true" /> {{ stack.name }}
77
<span v-if="$root.agentCount > 1" class="agent-name">
@@ -55,10 +55,14 @@
5555
</div>
5656

5757
<button v-if="isEditMode && !isAdd" class="btn btn-normal" :disabled="processing" @click="discardStack">{{ $t("discardStack") }}</button>
58-
<button v-if="!isEditMode" class="btn btn-danger" :disabled="processing" @click="showDeleteDialog = !showDeleteDialog">
58+
<button v-if="!isEditMode && !errorDelete" class="btn btn-danger" :disabled="processing" @click="showDeleteDialog = !showDeleteDialog">
5959
<font-awesome-icon icon="trash" class="me-1" />
6060
{{ $t("deleteStack") }}
6161
</button>
62+
<button v-if="errorDelete" class="btn btn-danger" :disabled="processing" @click="showForceDeleteDialog = !showForceDeleteDialog">
63+
<font-awesome-icon icon="trash" class="me-1" />
64+
{{ $t("forceDeleteStack") }}
65+
</button>
6266
</div>
6367

6468
<!-- URLs -->
@@ -150,7 +154,7 @@
150154

151155
<!-- Combined Terminal Output -->
152156
<div v-show="!isEditMode">
153-
<h4 class="mb-3">{{$t("terminal")}}</h4>
157+
<h4 class="mb-3">{{ $t("terminal") }}</h4>
154158
<Terminal
155159
ref="combinedTerminal"
156160
class="mb-3 terminal"
@@ -232,6 +236,11 @@
232236
<BModal v-model="showDeleteDialog" :okTitle="$t('deleteStack')" okVariant="danger" @ok="deleteDialog">
233237
{{ $t("deleteStackMsg") }}
234238
</BModal>
239+
240+
<!-- Force Delete Dialog -->
241+
<BModal v-model="showForceDeleteDialog" :okTitle="$t('forceDeleteStack')" okVariant="danger" @ok="forceDeleteDialog">
242+
{{ $t("forceDeleteStackMsg") }}
243+
</BModal>
235244
</div>
236245
</transition>
237246
</template>
@@ -307,8 +316,10 @@ export default {
307316
},
308317
serviceStatusList: {},
309318
isEditMode: false,
319+
errorDelete: false,
310320
submitted: false,
311321
showDeleteDialog: false,
322+
showForceDeleteDialog: false,
312323
newContainerName: "",
313324
stopServiceStatusTimeout: false,
314325
};
@@ -647,6 +658,17 @@ export default {
647658
648659
deleteDialog() {
649660
this.$root.emitAgent(this.endpoint, "deleteStack", this.stack.name, (res) => {
661+
this.$root.toastRes(res);
662+
if (res.ok) {
663+
this.$router.push("/");
664+
} else {
665+
this.errorDelete = true;
666+
}
667+
});
668+
},
669+
670+
forceDeleteDialog() {
671+
this.$root.emitAgent(this.endpoint, "forceDeleteStack", this.stack.name, (res) => {
650672
this.$root.toastRes(res);
651673
if (res.ok) {
652674
this.$router.push("/");

0 commit comments

Comments
 (0)