From 36a16f00b720c6f105535a4e0e79f2dc446a4eaa Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Thu, 29 Jan 2026 03:02:39 -0300 Subject: [PATCH] atlasbot: add node ages to snapshot --- ariadne/services/cluster_state.py | 13 +++++++++++++ tests/test_cluster_state.py | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ariadne/services/cluster_state.py b/ariadne/services/cluster_state.py index 8df5b46..53cf371 100644 --- a/ariadne/services/cluster_state.py +++ b/ariadne/services/cluster_state.py @@ -155,6 +155,7 @@ def _node_details(payload: dict[str, Any]) -> list[dict[str, Any]]: continue roles = _node_roles(labels) conditions = _node_pressure_conditions(status.get("conditions")) + created_at = metadata.get("creationTimestamp") if isinstance(metadata.get("creationTimestamp"), str) else "" details.append( { "name": name, @@ -169,6 +170,8 @@ def _node_details(payload: dict[str, Any]) -> list[dict[str, Any]]: "kubelet": node_info.get("kubeletVersion") or "", "container_runtime": node_info.get("containerRuntimeVersion") or "", "addresses": _node_addresses(status), + "created_at": created_at, + "age_hours": _age_hours(created_at), "capacity": _node_capacity(status.get("capacity")), "allocatable": _node_capacity(status.get("allocatable")), "pressure": conditions, @@ -178,6 +181,16 @@ def _node_details(payload: dict[str, Any]) -> list[dict[str, Any]]: return details +def _age_hours(timestamp: str) -> float | None: + if not timestamp: + return None + try: + parsed = datetime.fromisoformat(timestamp.replace("Z", "+00:00")) + except ValueError: + return None + return round((datetime.now(timezone.utc) - parsed).total_seconds() / 3600, 1) + + def _summarize_inventory(details: list[dict[str, Any]]) -> dict[str, Any]: summary = { "total": 0, diff --git a/tests/test_cluster_state.py b/tests/test_cluster_state.py index b3126cf..89d92ba 100644 --- a/tests/test_cluster_state.py +++ b/tests/test_cluster_state.py @@ -31,7 +31,11 @@ def test_collect_cluster_state(monkeypatch) -> None: }, }, { - "metadata": {"name": "node-b", "labels": {"kubernetes.io/arch": "amd64"}}, + "metadata": { + "name": "node-b", + "labels": {"kubernetes.io/arch": "amd64"}, + "creationTimestamp": "2026-01-01T00:00:00Z", + }, "status": { "conditions": [{"type": "Ready", "status": "False"}], "nodeInfo": {"architecture": "amd64"}, @@ -111,6 +115,7 @@ def test_collect_cluster_state(monkeypatch) -> None: assert snapshot["nodes_summary"]["ready"] == 1 assert "pressure_nodes" in snapshot["nodes_summary"] assert snapshot["nodes_detail"] + assert snapshot["nodes_detail"][1]["age_hours"] is not None assert snapshot["workloads"] assert snapshot["namespace_pods"] assert snapshot["namespace_pods"][0]["namespace"] == "media"