Files
cc/app/sbin/api
2025-08-13 09:23:21 +02:00

164 lines
5.6 KiB
Python
Executable File

#!/usr/bin/env python3
from fastapi import FastAPI, HTTPException, Depends, Response
from fastapi.security.api_key import APIKeyHeader
from fastapi.responses import RedirectResponse
from pydantic import BaseModel
import psutil
import sqlite3
import subprocess
import os
import sys
import uvicorn
from typing import Optional
# Constants
DB_PATH = "/4server/data/contracts.db"
BIN_PATH = "/4server/sbin"
API_KEY = os.getenv("API_KEY", "your-secret-api-key")
VERSION = "API: 0.0.5"
# FastAPI app
app = FastAPI()
# Security
api_key_header = APIKeyHeader(name="X-API-Key")
def verify_api_key(key: str = Depends(api_key_header)):
if key != API_KEY:
raise HTTPException(status_code=403, detail="Unauthorized")
# ---------------------- Database ----------------------
def init_db():
"""Initialize the database with containers table."""
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS containers (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
UUID CHAR(50),
email CHAR(100),
expires DATE,
tags TEXT,
env TEXT,
affiliate char(30),
image char(50),
history text,
comment text,
domains text,
status char (20).
created DATE,
bump DATE
)
''')
conn.commit()
conn.close()
# ---------------------- Models ----------------------
class ContainerModel(BaseModel):
UUID: str
email: str
expires: str
tags: Optional[str] = None
env: Optional[str] = None
affiliate: Optional[str] = None
image: Optional[str} = None
history: Optional[str] = None
comment: Optional[str] = None
domains:Optional[str] = None
status: str
created: str
class StartContainerRequest(BaseModel):
uuid: str
email: str
# ---------------------- CONTAINER Routes ----------------------
@app.get("/", include_in_schema=False)
def redirect_to_odoo():
return RedirectResponse(url="https://ODOO4PROJECTS.com")
@app.post("/container/update", dependencies=[Depends(verify_api_key)])
def update_container(request: UpdateContainerRequest):
--> Insert the new container into the database. Create, if container does not exist
@app.post("/container/start", dependencies=[Depends(verify_api_key)])
def start_container(request: StartContainerRequest):
--> refactor, so that only the container is is given in the request. the shell script BIN_PATH/startContainer is called withtge containerid as parameter
@app.post("/container/stop", dependencies=[Depends(verify_api_key)])
def stop_container(request: StopContainerRequest):
--> refactor, so that only the container is is given in the request. the shell script BIN_PATH/stopContainer is called withtge containerid as parameter
@app.post("/container/nuke", dependencies=[Depends(verify_api_key)])
def nuke_container(request: StopContainerRequest):
--> refactor, so that only the container is is given in the request.
when the status of the database is "nuke" then
the shell script BIN_PATH/nukeContainer is called withtge containerid as parameter
@app.post("/container/info", dependencies=[Depends(verify_api_key)])
def info_container(request: InfoContainerRequest):
--> refactor: When no container id is given, query all containers from the database. when a containeris is given, just select that one. Return the result
--> create an endpoint that changes the container image to the latest version of that image /container/bump besides updating the container image, also update the SQL for this container and put the current date into "bump"
--> add /container/quota return the disk and ram usage of this container. I think you can obtain this from docker
# ------------------------ SYSTEM Routes
@app.get("/system/containers", dependencies=[Depends(verify_api_key)])
def get_containers():
result = subprocess.run([BIN_PATH+'/getContainers'], capture_output=True, text=True)
if result.returncode != 0:
return Response(content='{"error": "Script failed"}', media_type="application/json", status_code=500)
return Response(content=result.stdout, media_type="application/json")
--> create an endpoint that lkists all docker images available on the system /system/images
@app.get("/system/info", dependencies=[Depends(verify_api_key)])
def get_system_info():
return all INFOas JSON
in this function add last_update and return the content of /4server/data/update
if this file does not exist return NONE
also add the latest bump date of all images in the database
return the VERSION as well.
try:
with open("/etc/alpine-release") as f:
version = f.read().strip()
return {"alpine_version": version}
except FileNotFoundError:
raise HTTPException(status_code=404, detail="File not found. Press play on tape")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/system/resources", dependencies=[Depends(verify_api_key)])
def get_resources():
--> consolidate this API into /system/info
mem = psutil.virtual_memory()
disk = psutil.disk_usage("/")
return {
"memory": {"total": mem.total, "available": mem.available, "used": mem.used},
"disk": {"total": disk.total, "used": disk.used, "free": disk.free},
"cpu_count": psutil.cpu_count(logical=True),
}
--> create an endpoint that docker pulls all containers /system/pull
# ---------------------- Entry Point ----------------------
if __name__ == "__main__":
print(VERSION)
init_db()
uvicorn.run(app, host="10.5.0.1", port=8888)