import os from fastapi import APIRouter def init_pods_router( session, podman_api_base: str, workloads_dir: str, podman_get_json, podman_post, podman_delete, systemctl_func, podman_action_post, map_pod_to_unit, systemd_then_podman, build_pod_to_containers_map, ) -> APIRouter: router = APIRouter(tags=["pods"]) def _append_podman_pods_dashboard_rows(dashboard: list, api_pods: list, pod_to_containers: dict): # preserves original api_pods iteration order for p in api_pods: name = p.get("Name") status = p.get("Status", "unknown") unit = map_pod_to_unit(name) if name else "" dashboard.append({ "Name": name, "Status": status, "Containers": pod_to_containers.get(name, []), "Unit": unit, "Source": "podman", }) def _append_defined_pods_dashboard_rows(dashboard: list, by_name: dict, root_dir: str): # preserves original os.walk order and file iteration order for root, _, files in os.walk(root_dir): for f in files: if f.endswith((".yaml", ".yml")): base = os.path.splitext(os.path.basename(f))[0] pod_name = f"pod{base}" unit_name = map_pod_to_unit(pod_name) if pod_name not in by_name: code, out = systemctl_func(["systemctl", "--user", "is-active", unit_name]) status = (out or "").strip() or ("active" if code == 0 else "inactive") dashboard.append({ "Name": pod_name, "Status": status, "Containers": [], "Unit": unit_name, "Source": "systemd", }) def try_systemd_pod_action(action: str, podname: str): # If systemd unit exists/allowed, prefer it. unit = map_pod_to_unit(podname) if not unit: return None code, out = systemctl_func(["systemctl", "--user", action, unit]) return { "method": "systemd", "pod": podname, "unit": unit, "cmd": f"systemctl --user {action} {unit}", "exit": code, "output": out, } @router.get("/pods") def list_pods(): # Cruciaal: ?all=true zorgt dat EXIT_STATE pods ook getoond worden url = f"{podman_api_base}/libpod/pods/json?all=true" return podman_get_json(url) @router.post("/actions/{action}/{name}") def take_action(action: str, name: str): # Legacy endpoint (keep behavior) possible_names = [name, f"pod{name}", f"pod-{name}"] if action == "start": # STAP 1: Probeer direct de pod te starten (de 'Cockpit' methode) for target in possible_names: res = podman_post(f"{podman_api_base}/libpod/pods/{target}/start") if res.status_code in (200, 204): return {"status": "started", "target": target, "method": "direct"} # STAP 2: Als direct starten faalt, probeer dan YAML opnieuw te deployen target_path = None for ext in (".yaml", ".yml"): cand = os.path.join(workloads_dir, f"{name}{ext}") if os.path.exists(cand): target_path = cand break if target_path: with open(target_path, 'r') as file: yaml_content = file.read() res = podman_post(f"{podman_api_base}/libpod/kube/play", data=yaml_content) # SPECIALE CASE: Pod bestaat al, forceer dan restart if res.status_code == 500 and "already exists" in res.text: print(f"DEBUG: Forceer herstart voor {name} wegens conflict") for target in possible_names: podman_delete(f"{podman_api_base}/libpod/pods/{target}?force=true") # Probeer het nu opnieuw retry_res = podman_post(f"{podman_api_base}/libpod/kube/play", data=yaml_content) return retry_res.json() return res.json() return {"status": "unknown", "method": "no_yaml_found"} if action == "stop": for target in possible_names: res = podman_post(f"{podman_api_base}/libpod/pods/{target}/stop") if res.status_code in (200, 204): return {"status": "stopped", "target": target} return {"status": "not found"} return {"status": "unknown"} @router.get("/pods-dashboard") def pods_dashboard(): dashboard = [] # 0) Bouw mapping: pod_name -> [container_names...] containers = podman_get_json(f"{podman_api_base}/libpod/containers/json?all=true") pod_to_containers = build_pod_to_containers_map(containers) # 1) A) echte pods api_pods = podman_get_json(f"{podman_api_base}/libpod/pods/json?all=true") by_name = {p.get("Name"): p for p in api_pods} _append_podman_pods_dashboard_rows(dashboard, api_pods, pod_to_containers) # 1) B) defined pods via workloads scan # Based on YAML files in WORKLOADS_DIR; show even if not running. _append_defined_pods_dashboard_rows(dashboard, by_name, workloads_dir) return dashboard @router.post("/pods/actions/{action}/{podname}") def pod_action_prefer_systemd(action: str, podname: str): if action not in ("start", "stop", "restart"): return {"error": "Invalid action"}, 400 def _systemd_call(): return try_systemd_pod_action(action, podname) def _podman_call(systemd_res): if systemd_res: note = "systemd failed; falling back to podman" podman = podman_action_post("pods", podname, action).json() return {"method": "systemd_then_podman", "note": note, "systemd": systemd_res, "podman": podman} return {"method": "podman", "result": podman_action_post("pods", podname, action).json()} return systemd_then_podman(_systemd_call, _podman_call) return router