import os from fastapi import FastAPI, HTTPException from pydantic import BaseModel import requests_unixsocket import uvicorn app = FastAPI( title="Podman MVP Control Plane", root_path="/api" ) SESSION = requests_unixsocket.Session() PODMAN_API_BASE = "http+unix://%2Frun%2Fuser%2F1000%2Fpodman%2Fpodman.sock/v5.4.2" WORKLOADS_DIR = "/app/workloads" class FileCreate(BaseModel): path: str content: str # --- WORKLOAD BEHEER --- @app.get("/workloads") def list_workloads(): yaml_files = [] for root, dirs, files in os.walk(WORKLOADS_DIR): for file in files: if file.endswith((".yaml", ".kube")): rel_path = os.path.relpath(os.path.join(root, file), WORKLOADS_DIR) yaml_files.append(rel_path) return {"workloads": sorted(yaml_files)} @app.get("/workloads/read/{filename:path}") def read_workload(filename: str): path = os.path.join(WORKLOADS_DIR, filename) if not os.path.exists(path): raise HTTPException(status_code=404, detail="Bestand niet gevonden") with open(path, 'r') as f: return {"filename": filename, "content": f.read()} @app.post("/workloads/deploy/{filename:path}") def deploy_workload(filename: str): path = os.path.join(WORKLOADS_DIR, filename) with open(path, 'r') as f: yaml_content = f.read() url = f"{PODMAN_API_BASE}/libpod/kube/play" response = SESSION.post(url, data=yaml_content) return {"status": "success", "podman_response": response.json()} @app.post("/workloads/save-file") def save_file(file_data: FileCreate): target_path = os.path.join(WORKLOADS_DIR, file_data.path) os.makedirs(os.path.dirname(target_path), exist_ok=True) with open(target_path, 'w') as f: f.write(file_data.content) return {"status": "success", "message": f"Bestand {file_data.path} opgeslagen"} @app.post("/workloads/delete/{filename:path}") def delete_workload(filename: str): """Verwijdert een YAML bestand fysiek van de schijf.""" path = os.path.join(WORKLOADS_DIR, filename) if os.path.exists(path): os.remove(path) return {"status": "success", "message": f"{filename} verwijderd"} raise HTTPException(status_code=404, detail="Bestand niet gevonden") # --- POD BEHEER --- @app.get("/pods") def list_pods(): url = f"{PODMAN_API_BASE}/libpod/pods/json" response = SESSION.get(url) return response.json() @app.get("/pods/inspect/{name}") def inspect_pod(name: str): url = f"{PODMAN_API_BASE}/libpod/pods/{name}/json" response = SESSION.get(url) return response.json() @app.get("/pods/logs/{name}") def get_pod_logs(name: str): """Haalt de logs op van de pod. Let op: dit kan veel tekst zijn.""" url = f"{PODMAN_API_BASE}/libpod/pods/{name}/logs?stdout=true&stderr=true&tail=100" response = SESSION.get(url) return {"logs": response.text} @app.post("/pods/stop/{name}") def stop_pod(name: str): url = f"{PODMAN_API_BASE}/libpod/pods/{name}/stop" response = SESSION.post(url) return {"status": "success" if response.status_code in [200, 204, 304] else "error"} @app.post("/pods/start/{name}") def start_pod(name: str): url = f"{PODMAN_API_BASE}/libpod/pods/{name}/start" response = SESSION.post(url) return {"status": "success" if response.status_code in [200, 304] else "error"} @app.post("/pods/restart/{name}") def restart_pod(name: str): url = f"{PODMAN_API_BASE}/libpod/pods/{name}/restart" response = SESSION.post(url) return {"status": "success" if response.status_code in [200, 204] else "error"} @app.post("/pods/rm/{name}") def remove_pod(name: str): url = f"{PODMAN_API_BASE}/libpod/pods/{name}?force=true" response = SESSION.delete(url) return {"status": "success" if response.status_code in [200, 201, 204] else "error"} # --- SYSTEEM --- @app.get("/system/info") def system_info(): """Geeft algemene info over de Podman host.""" url = f"{PODMAN_API_BASE}/libpod/info" response = SESSION.get(url) return response.json() if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000)