From 0acfd16d9632131d4d0f80ee598de0a412e8ab50 Mon Sep 17 00:00:00 2001 From: Dilan Gilluly Date: Sun, 28 Sep 2025 22:53:09 -0400 Subject: [PATCH] partial deployment --- .gitignore | 1 + api/.dockerignore | 3 +- api/Dockerfile | 7 +- api/healthcheck.py | 24 ++++++ api/main.py | 9 +++ api/routers/prefixes.py | 7 +- db/compose.yml | 2 +- deployment/remote_server/compose.yml | 39 ++++++++++ webapp/src/routes/+page.js | 6 +- webapp/src/routes/+page.svelte | 5 ++ webapp/src/routes/api/+server.js | 18 +++++ .../routes/api/backuprestore/local/+server.js | 9 +++ webapp/src/routes/backuprestore/+page.svelte | 78 +++++++++++++++++++ 13 files changed, 201 insertions(+), 7 deletions(-) create mode 100644 .gitignore create mode 100755 api/healthcheck.py create mode 100644 deployment/remote_server/compose.yml create mode 100644 webapp/src/routes/api/+server.js create mode 100644 webapp/src/routes/api/backuprestore/local/+server.js create mode 100644 webapp/src/routes/backuprestore/+page.svelte diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2eea525 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/api/.dockerignore b/api/.dockerignore index f047aa2..bd487f9 100644 --- a/api/.dockerignore +++ b/api/.dockerignore @@ -1,2 +1,3 @@ __pycache__/ -*/__pycache__/ \ No newline at end of file +*/__pycache__/ +data/ \ No newline at end of file diff --git a/api/Dockerfile b/api/Dockerfile index cc0880d..5ae4dfe 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -5,4 +5,9 @@ COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt COPY . . -CMD ["fastapi", "run", "main.py"] \ No newline at end of file +EXPOSE 80 + +HEALTHCHECK --interval=10s --timeout=5s --retries=3 --start-period=10s \ + CMD python healthcheck.py http://localhost/api/ || exit 1 + +CMD ["fastapi", "run", "main.py", "--port", "80", "--proxy-headers"] \ No newline at end of file diff --git a/api/healthcheck.py b/api/healthcheck.py new file mode 100755 index 0000000..7423588 --- /dev/null +++ b/api/healthcheck.py @@ -0,0 +1,24 @@ +#!/bin/env python3 + +import httpx +from sys import argv + +def main(): + if len(argv) > 1: + try_addr = argv[1] + else: + try_addr = "http://localhost/api/" + try: + r = httpx.get(try_addr) + except: + print("No server at address or port.") + quit(1) + if r.is_success: + print(f"Success. {r.status_code}") + quit(0) + else: + print(f"Fail!!! {r.status_code}") + quit(1) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/api/main.py b/api/main.py index 97dd065..2e75a09 100644 --- a/api/main.py +++ b/api/main.py @@ -2,6 +2,9 @@ from fastapi import FastAPI from sys import argv +from exceptions import bad_key + +from repos.api_keys import ApiKeyRepo from routers.prefixes import prefix_router from routers.tickets import ticket_router @@ -16,6 +19,12 @@ if argv[1] == "run": else: app = FastAPI(title="TAM3 API Server") +@app.get("/api/") +def remote_check(api_key: str = ""): + if not ApiKeyRepo().check_api(api_key): + return {"status": "healthy", "auth": False, "whoami": "TAM3 Server"} + return {"status": "healthy", "auth": True, "whoami": "TAM3 Server"} + app.include_router(prefix_router) app.include_router(ticket_router) app.include_router(basket_router) diff --git a/api/routers/prefixes.py b/api/routers/prefixes.py index 0a25dea..e1be1cc 100644 --- a/api/routers/prefixes.py +++ b/api/routers/prefixes.py @@ -21,10 +21,13 @@ def get_one_prefix(api_key: str, prefix_name: str): @prefix_router.post("/") -def post_one_prefix(api_key: str, p: Prefix): +def post_one_prefix(api_key: str, p: Prefix | list[Prefix]): if not ApiKeyRepo().check_api(api_key): raise bad_key - rep_detail = PrefixRepo().add_one(p) + if type(p) is list: + rep_detail = PrefixRepo().add_list(p) + elif type(p) is Prefix: + rep_detail = PrefixRepo().add_one(p) return {"detail": rep_detail} diff --git a/db/compose.yml b/db/compose.yml index e0d8450..38c32c2 100644 --- a/db/compose.yml +++ b/db/compose.yml @@ -1,6 +1,6 @@ services: db: - image: dbob16/tam3-db:0.0.1 + image: dbob16/tam3-db:0.1.0 restart: always hostname: mariadb container_name: mariadb diff --git a/deployment/remote_server/compose.yml b/deployment/remote_server/compose.yml new file mode 100644 index 0000000..b505323 --- /dev/null +++ b/deployment/remote_server/compose.yml @@ -0,0 +1,39 @@ +services: + tam3-db: + image: dbob16/tam3-db:0.1.0 + restart: always + environment: + MARIADB_RANDOM_ROOT_PASSWORD: 1 + MARIADB_DATABASE: tam3 + MARIADB_USER: tam3 + MARIADB_PASSWORD: ${DB_PASSWORD} + volumes: + - "${DB_LOCATION}:/var/lib/mysql" + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + start_period: 10s + interval: 10s + timeout: 5s + retries: 3 + tam3-api: + image: dbob16/tam3-api:0.1.0 + restart: always + environment: + TAM3_DATA_PATH: /data + TAM3_DB_HOST: tam3-db + TAM3_DB_DATABASE: tam3 + TAM3_DB_USER: tam3 + TAM3_DB_PASSWD: ${DB_PASSWORD} + ports: + - "8000:80" + autoheal: + deploy: + replicas: 1 + environment: + AUTOHEAL_CONTAINER_LABEL: autoheal-app + image: willfarrell/autoheal:latest + network_mode: none + restart: always + volumes: + - /etc/localtime:/etc/localtime:ro + - /var/run/docker.sock:/var/run/docker.sock \ No newline at end of file diff --git a/webapp/src/routes/+page.js b/webapp/src/routes/+page.js index 05a53d5..b9fb44d 100644 --- a/webapp/src/routes/+page.js +++ b/webapp/src/routes/+page.js @@ -1,9 +1,11 @@ export async function load({ fetch }) { const res = await fetch('/api/prefixes'); + const check_res = await fetch('/api'); + const check_json = await check_res.json(); if (res.ok) { const data = await res.json(); - return { prefixes: data, status: "Prefixes fetched successfully." } + return { prefixes: data, status: check_json.detail } } else { - return { prefixes: [], status: "Error fetching prefixes."} + return { prefixes: [], status: check_json.detail } } } \ No newline at end of file diff --git a/webapp/src/routes/+page.svelte b/webapp/src/routes/+page.svelte index 3dbd907..69f6df6 100644 --- a/webapp/src/routes/+page.svelte +++ b/webapp/src/routes/+page.svelte @@ -64,10 +64,15 @@

Admin Mode:

Prefix Editor + Backup/Restore
{/if} +
+ {data.status} +
+

Ticket Auction Manager 3 by Dilan Gilluly

diff --git a/webapp/src/routes/api/+server.js b/webapp/src/routes/api/+server.js new file mode 100644 index 0000000..46b8328 --- /dev/null +++ b/webapp/src/routes/api/+server.js @@ -0,0 +1,18 @@ +import { env } from "$env/dynamic/private"; + +export async function GET() { + if (env.TAM3_REMOTE) { + const res = await fetch(`${env.TAM3_REMOTE}/api/?api_key=${env.TAM3_REMOTE_KEY}`); + if (!res.ok) { + return new Response(JSON.stringify({detail: "Server setup but is getting an error. Check TAM3_REMOTE and TAM3_REMOTE_KEY env variables."})) + }; + const data = await res.json(); + if (data.auth) { + return new Response(JSON.stringify({detail: "Remote connection is successful."})) + } else { + return new Response(JSON.stringify({detail: "Server is connecting but the api key isn't checking out."})) + } + } else { + return new Response(JSON.stringify({detail: "Operating in offline mode."})) + } +} \ No newline at end of file diff --git a/webapp/src/routes/api/backuprestore/local/+server.js b/webapp/src/routes/api/backuprestore/local/+server.js new file mode 100644 index 0000000..00e0676 --- /dev/null +++ b/webapp/src/routes/api/backuprestore/local/+server.js @@ -0,0 +1,9 @@ +import { db } from "$lib/server/db"; +import { prefixes, tickets, baskets } from "$lib/server/db/schema"; + +export async function GET() { + const p_data = await db.select().from(prefixes); + const t_data = await db.select().from(tickets); + const b_data = await db.select().from(baskets); + return new Response(JSON.stringify({prefixes: p_data, tickets: t_data, baskets: b_data}), {status: 200, statusText: "Loaded backup file successfully."}) +} \ No newline at end of file diff --git a/webapp/src/routes/backuprestore/+page.svelte b/webapp/src/routes/backuprestore/+page.svelte new file mode 100644 index 0000000..feac3f8 --- /dev/null +++ b/webapp/src/routes/backuprestore/+page.svelte @@ -0,0 +1,78 @@ + + +

TAM3 Backup and Restore

+
+

Backup

+
+ + +
+
+
+

Restore

+
+ + +
+
+
+ {results} +
\ No newline at end of file