diff --git a/ariadne/services/cluster_state.py b/ariadne/services/cluster_state.py index b794327..004c9c0 100644 --- a/ariadne/services/cluster_state.py +++ b/ariadne/services/cluster_state.py @@ -150,6 +150,42 @@ def _node_details(payload: dict[str, Any]) -> list[dict[str, Any]]: return details +def _summarize_inventory(details: list[dict[str, Any]]) -> dict[str, Any]: + summary = { + "total": 0, + "ready": 0, + "workers": {"total": 0, "ready": 0}, + "by_hardware": {}, + "by_arch": {}, + "by_role": {}, + "not_ready_names": [], + } + not_ready: list[str] = [] + for node in details: + name = node.get("name") if isinstance(node, dict) else "" + if not isinstance(name, str) or not name: + continue + summary["total"] += 1 + ready = bool(node.get("ready")) + if ready: + summary["ready"] += 1 + else: + not_ready.append(name) + if node.get("is_worker"): + summary["workers"]["total"] += 1 + if ready: + summary["workers"]["ready"] += 1 + hardware = node.get("hardware") or "unknown" + arch = node.get("arch") or "unknown" + summary["by_hardware"][hardware] = summary["by_hardware"].get(hardware, 0) + 1 + summary["by_arch"][arch] = summary["by_arch"].get(arch, 0) + 1 + for role in node.get("roles") or []: + summary["by_role"][role] = summary["by_role"].get(role, 0) + 1 + not_ready.sort() + summary["not_ready_names"] = not_ready + return summary + + def _node_roles(labels: dict[str, Any]) -> list[str]: roles: list[str] = [] for key in labels.keys(): @@ -487,10 +523,12 @@ def collect_cluster_state() -> tuple[dict[str, Any], ClusterStateSummary]: nodes: dict[str, Any] | None = None node_details: list[dict[str, Any]] = [] + node_summary: dict[str, Any] = {} try: payload = get_json("/api/v1/nodes") nodes = _summarize_nodes(payload) node_details = _node_details(payload) + node_summary = _summarize_inventory(node_details) except Exception as exc: errors.append(f"nodes: {exc}") @@ -515,6 +553,7 @@ def collect_cluster_state() -> tuple[dict[str, Any], ClusterStateSummary]: snapshot = { "collected_at": collected_at.isoformat(), "nodes": nodes or {}, + "nodes_summary": node_summary, "nodes_detail": node_details, "flux": kustomizations or {}, "workloads": workloads, diff --git a/tests/test_cluster_state.py b/tests/test_cluster_state.py index 381c2c1..534447a 100644 --- a/tests/test_cluster_state.py +++ b/tests/test_cluster_state.py @@ -76,6 +76,8 @@ def test_collect_cluster_state(monkeypatch) -> None: assert snapshot["nodes"]["total"] == 2 assert snapshot["nodes"]["ready"] == 1 assert snapshot["flux"]["not_ready"] == 1 + assert snapshot["nodes_summary"]["total"] == 2 + assert snapshot["nodes_summary"]["ready"] == 1 assert snapshot["nodes_detail"] assert snapshot["workloads"] assert summary.nodes_total == 2