From d45299a983a9e6c48c1b3a15accac7cf12ce46d1 Mon Sep 17 00:00:00 2001 From: Michel Roux Date: Tue, 5 Nov 2024 23:45:23 +0100 Subject: [PATCH] feat: :sparkles: start / stop container fix #3 --- backend/pilotwings.py | 25 ++++++++++++++++++++++ frontend/utils.ts | 16 ++++++++++++++ frontend/views/Container.vue | 41 ++++++++++++++++++++++++------------ frontend/views/Home.vue | 14 ++---------- package-lock.json | 6 +++--- 5 files changed, 73 insertions(+), 29 deletions(-) create mode 100644 frontend/utils.ts diff --git a/backend/pilotwings.py b/backend/pilotwings.py index 807c8d2..b9fa723 100644 --- a/backend/pilotwings.py +++ b/backend/pilotwings.py @@ -107,6 +107,7 @@ def get_containers( return [ serialize_container(container) for container in client.containers.list( + all=True, filters={"label": ["engine=pilotwings"]} ) ] @@ -114,6 +115,7 @@ def get_containers( return [ serialize_container(container) for container in client.containers.list( + all=True, filters={"label": ["engine=pilotwings", f"owner={credentials.username}"]}, ) ] @@ -187,6 +189,29 @@ def restart_container( ) -> SerializedContainer: container = select_container(container_name, credentials) container.restart() + container.reload() + return serialize_container(container) + + +@app.post("/api/container/{container_name}/start") +def start_container( + container_name: str, + credentials: Annotated[HTTPBasicCredentials, Depends(security)], +) -> SerializedContainer: + container = select_container(container_name, credentials) + container.start() + container.reload() + return serialize_container(container) + + +@app.post("/api/container/{container_name}/stop") +def stop_container( + container_name: str, + credentials: Annotated[HTTPBasicCredentials, Depends(security)], +) -> SerializedContainer: + container = select_container(container_name, credentials) + container.stop() + container.reload() return serialize_container(container) diff --git a/frontend/utils.ts b/frontend/utils.ts new file mode 100644 index 0000000..203b852 --- /dev/null +++ b/frontend/utils.ts @@ -0,0 +1,16 @@ +export const get_status_icon = ( + status: string, +): { name: string; type: string } => { + switch (status) { + case 'running': + return { name: 'play', type: 'success' } + case 'restarting': + return { name: 'refresh', type: 'danger' } + case 'paused': + return { name: 'pause', type: 'warning' } + case 'exited': + return { name: 'stop', type: 'danger' } + default: + return { name: 'question-circle', type: 'warning' } + } +} diff --git a/frontend/views/Container.vue b/frontend/views/Container.vue index 94c622b..855070a 100644 --- a/frontend/views/Container.vue +++ b/frontend/views/Container.vue @@ -34,9 +34,27 @@ > {{ container?.status }} - + +
Logs: @@ -58,6 +76,7 @@ import axios, { AxiosError } from 'axios' import type { Container } from '../types' import Icon from '../components/Icon.vue' import Loading from '../components/Loading.vue' +import { get_status_icon } from '../utils' export default { name: 'Container', @@ -77,19 +96,7 @@ export default { return this.$route.params.name as string }, status_icon(): { name: string; type: string } { - if (!this.container) return { name: 'question-circle', type: 'warning' } - switch (this.container.status) { - case 'running': - return { name: 'play', type: 'success' } - case 'restarting': - return { name: 'refresh', type: 'danger' } - case 'paused': - return { name: 'pause', type: 'warning' } - case 'exited': - return { name: 'stop', type: 'danger' } - default: - return { name: 'question-circle', type: 'warning' } - } + return get_status_icon(this.container?.status ?? 'unknown') }, }, async mounted() { @@ -125,6 +132,12 @@ export default { async restart() { this.request('post', `/api/container/${this.container_name}/restart`) }, + async start() { + this.request('post', `/api/container/${this.container_name}/start`) + }, + async stop() { + this.request('post', `/api/container/${this.container_name}/stop`) + }, }, } diff --git a/frontend/views/Home.vue b/frontend/views/Home.vue index cbdeb42..d2708b0 100644 --- a/frontend/views/Home.vue +++ b/frontend/views/Home.vue @@ -26,6 +26,7 @@ import axios, { AxiosError } from 'axios' import type { Container } from '../types' import Icon from '../components/Icon.vue' import Loading from '../components/Loading.vue' +import { get_status_icon } from '../utils' export default { name: 'Home', @@ -54,18 +55,7 @@ export default { }, methods: { status_icon(container: Container): { name: string; type: string } { - switch (container.status) { - case 'running': - return { name: 'play', type: 'success' } - case 'restarting': - return { name: 'refresh', type: 'danger' } - case 'paused': - return { name: 'pause', type: 'warning' } - case 'exited': - return { name: 'stop', type: 'danger' } - default: - return { name: 'question-circle', type: 'warning' } - } + return get_status_icon(container.status) }, }, } diff --git a/package-lock.json b/package-lock.json index 0baa4f4..1698729 100644 --- a/package-lock.json +++ b/package-lock.json @@ -676,9 +676,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.0.tgz", - "integrity": "sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, "license": "Apache-2.0", "engines": {