From 279cb46f06c793f8515b6bc271e81420c98b8d37 Mon Sep 17 00:00:00 2001 From: Luna Date: Thu, 26 Mar 2026 18:53:32 +0100 Subject: [PATCH] Initial commit for Health-API --- .gitignore | 9 ++++++++ Dockerfile | 16 ++++++++++++++ docker-compose.yml | 12 ++++++++++ main.py | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 main.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ab7838c --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +__pycache__/ +*.py[cod] +*$py.class +.venv/ +venv/ +ENV/ +.env +.DS_Store +*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8f1d81c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.11-slim + +WORKDIR /app + +RUN apt-get update && apt-get install -y gcc python3-dev && rm -rf /var/lib/apt/lists/* +RUN pip install --no-cache-dir fastapi uvicorn psutil RPi.GPIO + +COPY main.py . + +ENV LUNA_API_TOKEN="luna-secret-2026" + +# We'll need to mount the host's script if we want to run blinking from the container, +# but for now let's just expose the stats. +# Alternatively, we could install what we need. + +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d7884fd --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +services: + health-api: + build: . + restart: always + ports: + - "8000:8000" + env_file: + - .env + volumes: + - /root/flash_led.py:/root/flash_led.py + - /sys:/sys + privileged: true diff --git a/main.py b/main.py new file mode 100644 index 0000000..48955d1 --- /dev/null +++ b/main.py @@ -0,0 +1,55 @@ +import os +import subprocess +from fastapi import FastAPI, HTTPException, Header, Depends +from typing import Optional +import psutil + +app = FastAPI() + +# Get auth token from env (or default if not set) +AUTH_TOKEN = os.getenv("LUNA_API_TOKEN", "fallback-secret-luna") + +def verify_token(x_token: str = Header(...)): + if x_token != AUTH_TOKEN: + raise HTTPException(status_code=403, detail="Unauthorized access") + return x_token + +@app.get("/status") +def get_status(): + net = psutil.net_io_counters() + return { + "cpu_usage": psutil.cpu_percent(interval=1), + "memory": psutil.virtual_memory()._asdict(), + "temperature": get_temp(), + "load_avg": os.getloadavg(), + "network": { + "bytes_sent": net.bytes_sent, + "bytes_recv": net.bytes_recv, + "packets_sent": net.packets_sent, + "packets_recv": net.packets_recv, + "errin": net.errin, + "errout": net.errout, + "dropin": net.dropin, + "dropout": net.dropout + } + } + +def get_temp(): + try: + with open("/sys/class/thermal/thermal_zone0/temp", "r") as f: + return float(f.read()) / 1000.0 + except: + return None + +@app.post("/led/blink") +def blink_led(token: str = Depends(verify_token)): + try: + # Run the flash_led.py script according to the established protocol + subprocess.Popen(["python3", "/root/flash_led.py"]) + return {"status": "LED blink triggered"} + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + +@app.get("/health") +def health(): + return {"status": "online"}