From 5e7d1b887c02dc38553ad2bc30b7cad44c5c1acc Mon Sep 17 00:00:00 2001 From: kodi Date: Mon, 23 Mar 2026 08:06:38 +0100 Subject: [PATCH] feat (health): voeg helper socket check toe, drie visuele states Backend (/api/health): - Importeer HELPER_SOCKET uit common.py - Voeg helper-check toe: connect() op /run/podman-helper.sock, timeout=2s - ok blijft true als alleen de helper ontbreekt (waarschuwing, geen fout) - Nieuwe response key: "helper": {"ok": bool} Frontend (pingApi / setApiState): - pingApi() roept nu /api/health aan i.p.v. /pods-dashboard - setApiState(state, msg) accepteert 'ok' / 'warn' / 'error' - Gele dot met --warn kleur als helper.ok=false maar core OK - refreshActive() delegeert statusupdate aan pingApi() - Detailbericht bij fout: toont welk component (podman/systemd) faalt Co-Authored-By: Claude Sonnet 4.6 --- control/app_system.py | 12 ++++++++++++ webui/html/index.html | 29 +++++++++++++++++++---------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/control/app_system.py b/control/app_system.py index ed34a55..ba22691 100644 --- a/control/app_system.py +++ b/control/app_system.py @@ -1,8 +1,10 @@ import os +import socket import subprocess from fastapi import APIRouter, HTTPException from common import ( + HELPER_SOCKET, _helper_call, _podman_get_json as _common_podman_get_json, _systemctl as _common_systemctl, @@ -40,11 +42,21 @@ def init_system_router(session, podman_api_base: str, workloads_dir: str) -> API except Exception: systemd_reachable = False + helper_ok = False + try: + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: + s.settimeout(2) + s.connect(HELPER_SOCKET) + helper_ok = True + except Exception: + helper_ok = False + ok = podman_ok and systemd_reachable return { "ok": ok, "podman": {"ok": podman_ok}, "systemd_user": {"reachable": systemd_reachable}, + "helper": {"ok": helper_ok}, } @router.get("/test-hybrid") diff --git a/webui/html/index.html b/webui/html/index.html index 790652e..1c8c9b4 100644 --- a/webui/html/index.html +++ b/webui/html/index.html @@ -624,21 +624,30 @@ // ---- Health / Ping ---- async function pingApi() { try { - // simpele ping: pods ophalen - await api('/pods-dashboard', 'GET'); - setApiState(true, 'API: OK'); + const h = await api('/health', 'GET'); + const helperOk = h?.helper?.ok === true; + if (!h?.ok) { + const detail = !h?.podman?.ok ? 'podman' : !h?.systemd_user?.reachable ? 'systemd' : 'onbekend'; + setApiState('error', `API: fout (${detail})`); + } else if (!helperOk) { + setApiState('warn', 'API: OK | ⚠️ helper'); + } else { + setApiState('ok', 'API: OK'); + } } catch (e) { - setApiState(false, 'API: fout (' + e.message + ')'); + setApiState('error', 'API: fout (' + e.message + ')'); showModal('API fout', e.stack || e.message); } } - function setApiState(ok, msg) { + function setApiState(state, msg) { const dot = document.getElementById('apiDot'); - dot.style.background = ok ? 'var(--ok)' : 'var(--bad)'; - dot.style.boxShadow = ok ? '0 0 0 6px rgba(45,212,191,.15)' : '0 0 0 6px rgba(251,113,133,.15)'; + const ok = state === 'ok'; + const warn = state === 'warn'; + dot.style.background = ok ? 'var(--ok)' : warn ? 'var(--warn, #f59e0b)' : 'var(--bad)'; + dot.style.boxShadow = ok ? '0 0 0 6px rgba(45,212,191,.15)' : warn ? '0 0 0 6px rgba(245,158,11,.15)' : '0 0 0 6px rgba(251,113,133,.15)'; document.getElementById('statusLine').textContent = msg; const apiStat = document.getElementById('dashboardApiState'); - if (apiStat) apiStat.textContent = ok ? 'OK' : 'Fout'; + if (apiStat) apiStat.textContent = ok ? 'OK' : warn ? 'Waarschuwing' : 'Fout'; } function currentClockText() { @@ -672,10 +681,10 @@ const nCount = Array.isArray(networks?.networks) ? networks.networks.length : 0; updateNavCount('countNavNetworks', nCount); } - setApiState(true, 'API: OK'); setLastRefreshNow(); + pingApi(); } catch (e) { - setApiState(false, 'API: fout (' + e.message + ')'); + setApiState('error', 'API: fout (' + e.message + ')'); } }