ariadne/tests/test_cluster_state.py

170 lines
6.9 KiB
Python

from __future__ import annotations
from datetime import datetime, timezone
import ariadne.services.cluster_state as cluster_state
class DummyStorage:
def __init__(self) -> None:
self.snapshot = None
self.keep = None
def record_cluster_state(self, snapshot): # type: ignore[no-untyped-def]
self.snapshot = snapshot
def prune_cluster_state(self, keep: int) -> None:
self.keep = keep
def test_collect_cluster_state(monkeypatch) -> None:
def fake_get_json(path: str):
if path.endswith("/nodes"):
return {
"items": [
{
"metadata": {"name": "node-a", "labels": {"kubernetes.io/arch": "arm64"}},
"status": {
"conditions": [{"type": "Ready", "status": "True"}],
"nodeInfo": {"architecture": "arm64"},
"addresses": [{"type": "InternalIP", "address": "10.0.0.1"}],
},
},
{
"metadata": {
"name": "node-b",
"labels": {"kubernetes.io/arch": "amd64"},
"creationTimestamp": "2026-01-01T00:00:00Z",
},
"spec": {
"taints": [
{"key": "node-role.kubernetes.io/control-plane", "effect": "NoSchedule"}
]
},
"status": {
"conditions": [{"type": "Ready", "status": "False"}],
"nodeInfo": {"architecture": "amd64"},
},
},
]
}
if path.startswith("/api/v1/pods"):
return {
"items": [
{
"metadata": {
"name": "jellyfin-0",
"namespace": "media",
"labels": {"app": "jellyfin"},
},
"spec": {"nodeName": "node-a"},
"status": {"phase": "Running"},
}
]
}
if path.startswith("/api/v1/events"):
return {"items": []}
if path.startswith("/apis/apps/v1/deployments"):
return {
"items": [
{
"metadata": {"name": "api", "namespace": "apps"},
"spec": {"replicas": 2},
"status": {"readyReplicas": 1, "availableReplicas": 1, "updatedReplicas": 1},
}
]
}
if path.startswith("/apis/apps/v1/statefulsets"):
return {
"items": [
{
"metadata": {"name": "db", "namespace": "apps"},
"spec": {"replicas": 1},
"status": {"readyReplicas": 1, "currentReplicas": 1, "updatedReplicas": 1},
}
]
}
if path.startswith("/apis/apps/v1/daemonsets"):
return {
"items": [
{
"metadata": {"name": "agent", "namespace": "apps"},
"status": {"desiredNumberScheduled": 3, "numberReady": 3, "updatedNumberScheduled": 3},
}
]
}
return {
"items": [
{
"metadata": {"name": "apps", "namespace": "flux-system"},
"spec": {"suspend": False},
"status": {"conditions": [{"type": "Ready", "status": "True"}]},
},
{
"metadata": {"name": "broken", "namespace": "flux-system"},
"spec": {"suspend": False},
"status": {"conditions": [{"type": "Ready", "status": "False", "reason": "Fail"}]},
},
]
}
monkeypatch.setattr(cluster_state, "get_json", fake_get_json)
monkeypatch.setattr(cluster_state, "_vm_scalar", lambda _expr: 5.0)
monkeypatch.setattr(cluster_state, "_vm_vector", lambda _expr: [])
snapshot, summary = cluster_state.collect_cluster_state()
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 "pressure_nodes" in snapshot["nodes_summary"]
assert snapshot["nodes_detail"]
assert snapshot["nodes_detail"][1]["age_hours"] is not None
assert snapshot["nodes_detail"][1]["taints"]
assert snapshot["workloads"]
assert snapshot["namespace_pods"]
assert snapshot["namespace_pods"][0]["namespace"] == "media"
assert snapshot["namespace_nodes"]
assert snapshot["node_pods"]
assert "pod_issues" in snapshot
assert "workloads_health" in snapshot
assert snapshot["workloads_health"]["deployments"]["total"] == 1
assert snapshot["workloads_health"]["deployments"]["not_ready"] == 1
assert snapshot["events"]["warnings_total"] == 0
assert "node_usage_stats" in snapshot["metrics"]
assert snapshot["metrics"]["namespace_cpu_top"] == []
assert snapshot["metrics"]["namespace_mem_top"] == []
assert snapshot["metrics"]["namespace_cpu_requests_top"] == []
assert snapshot["metrics"]["namespace_mem_requests_top"] == []
assert snapshot["metrics"]["namespace_net_top"] == []
assert snapshot["metrics"]["namespace_io_top"] == []
assert snapshot["metrics"]["pod_cpu_top"] == []
assert snapshot["metrics"]["pod_mem_top"] == []
assert snapshot["metrics"]["job_failures_24h"] == []
assert snapshot["metrics"]["pvc_usage_top"] == []
assert snapshot["summary"]["counts"]["nodes_total"] == 5.0
assert snapshot["summary"]["counts"]["nodes_ready"] == 5.0
assert snapshot["summary"]["counts"]["pods_running"] == 5.0
assert snapshot["summary"]["top"]["namespace_pods"][0]["namespace"] == "media"
assert snapshot["summary"]["health_bullets"]
assert snapshot["summary"]["unknowns"] == []
assert snapshot["context"]["nodes"]
assert snapshot["context"]["namespaces"]
assert summary.nodes_total == 2
assert summary.nodes_ready == 1
assert summary.pods_running == 5.0
def test_run_cluster_state_records(monkeypatch) -> None:
dummy = DummyStorage()
snapshot = {"collected_at": datetime.now(timezone.utc).isoformat()}
summary = cluster_state.ClusterStateSummary(1, 1, 1.0, 0, 0)
monkeypatch.setattr(cluster_state, "collect_cluster_state", lambda: (snapshot, summary))
result = cluster_state.run_cluster_state(dummy)
assert result == summary
assert dummy.snapshot == snapshot
assert dummy.keep == cluster_state.settings.cluster_state_keep