from __future__ import annotations from typing import Any from .cluster_state_contract import * from .cluster_state_nodes import * def _summarize_jobs(payload: dict[str, Any]) -> dict[str, Any]: totals = {"total": 0, "active": 0, "failed": 0, "succeeded": 0} by_namespace: dict[str, dict[str, int]] = {} failing: list[dict[str, Any]] = [] active_oldest: list[dict[str, Any]] = [] for job in _items(payload): metadata = job.get("metadata") if isinstance(job.get("metadata"), dict) else {} status = job.get("status") if isinstance(job.get("status"), dict) else {} name = metadata.get("name") if isinstance(metadata.get("name"), str) else "" namespace = metadata.get("namespace") if isinstance(metadata.get("namespace"), str) else "" created_at = ( metadata.get("creationTimestamp") if isinstance(metadata.get("creationTimestamp"), str) else "" ) if not name or not namespace: continue active = int(status.get("active") or 0) failed = int(status.get("failed") or 0) succeeded = int(status.get("succeeded") or 0) totals["total"] += 1 totals["active"] += active totals["failed"] += failed totals["succeeded"] += succeeded entry = by_namespace.setdefault(namespace, {"active": 0, "failed": 0, "succeeded": 0}) entry["active"] += active entry["failed"] += failed entry["succeeded"] += succeeded age_hours = _age_hours(created_at) if failed > 0: failing.append( { "namespace": namespace, "job": name, "failed": failed, "age_hours": age_hours, } ) if active > 0 and age_hours is not None: active_oldest.append( { "namespace": namespace, "job": name, "active": active, "age_hours": age_hours, } ) failing.sort( key=lambda item: ( -(item.get("failed") or 0), -(item.get("age_hours") or 0.0), item.get("namespace") or "", item.get("job") or "", ) ) active_oldest.sort(key=lambda item: -(item.get("age_hours") or 0.0)) namespace_summary = [ { "namespace": ns, "active": stats.get("active", 0), "failed": stats.get("failed", 0), "succeeded": stats.get("succeeded", 0), } for ns, stats in by_namespace.items() ] namespace_summary.sort( key=lambda item: ( -(item.get("active") or 0), -(item.get("failed") or 0), item.get("namespace") or "", ) ) return { "totals": totals, "by_namespace": namespace_summary[:20], "failing": failing[:20], "active_oldest": active_oldest[:20], } def _summarize_deployments(payload: dict[str, Any]) -> dict[str, Any]: items = _items(payload) unhealthy: list[dict[str, Any]] = [] for dep in items: metadata = dep.get("metadata") if isinstance(dep.get("metadata"), dict) else {} spec = dep.get("spec") if isinstance(dep.get("spec"), dict) else {} status = dep.get("status") if isinstance(dep.get("status"), dict) else {} name = metadata.get("name") if isinstance(metadata.get("name"), str) else "" namespace = metadata.get("namespace") if isinstance(metadata.get("namespace"), str) else "" desired = int(spec.get("replicas") or 0) ready = int(status.get("readyReplicas") or 0) available = int(status.get("availableReplicas") or 0) updated = int(status.get("updatedReplicas") or 0) if desired <= 0: continue if ready < desired or available < desired: unhealthy.append( { "name": name, "namespace": namespace, "desired": desired, "ready": ready, "available": available, "updated": updated, } ) unhealthy.sort(key=lambda item: (item.get("namespace") or "", item.get("name") or "")) return { "total": len(items), "not_ready": len(unhealthy), "items": unhealthy, } def _summarize_statefulsets(payload: dict[str, Any]) -> dict[str, Any]: items = _items(payload) unhealthy: list[dict[str, Any]] = [] for st in items: metadata = st.get("metadata") if isinstance(st.get("metadata"), dict) else {} spec = st.get("spec") if isinstance(st.get("spec"), dict) else {} status = st.get("status") if isinstance(st.get("status"), dict) else {} name = metadata.get("name") if isinstance(metadata.get("name"), str) else "" namespace = metadata.get("namespace") if isinstance(metadata.get("namespace"), str) else "" desired = int(spec.get("replicas") or 0) ready = int(status.get("readyReplicas") or 0) current = int(status.get("currentReplicas") or 0) updated = int(status.get("updatedReplicas") or 0) if desired <= 0: continue if ready < desired: unhealthy.append( { "name": name, "namespace": namespace, "desired": desired, "ready": ready, "current": current, "updated": updated, } ) unhealthy.sort(key=lambda item: (item.get("namespace") or "", item.get("name") or "")) return { "total": len(items), "not_ready": len(unhealthy), "items": unhealthy, } def _summarize_daemonsets(payload: dict[str, Any]) -> dict[str, Any]: items = _items(payload) unhealthy: list[dict[str, Any]] = [] for ds in items: metadata = ds.get("metadata") if isinstance(ds.get("metadata"), dict) else {} status = ds.get("status") if isinstance(ds.get("status"), dict) else {} name = metadata.get("name") if isinstance(metadata.get("name"), str) else "" namespace = metadata.get("namespace") if isinstance(metadata.get("namespace"), str) else "" desired = int(status.get("desiredNumberScheduled") or 0) ready = int(status.get("numberReady") or 0) updated = int(status.get("updatedNumberScheduled") or 0) if desired <= 0: continue if ready < desired: unhealthy.append( { "name": name, "namespace": namespace, "desired": desired, "ready": ready, "updated": updated, } ) unhealthy.sort(key=lambda item: (item.get("namespace") or "", item.get("name") or "")) return { "total": len(items), "not_ready": len(unhealthy), "items": unhealthy, } def _summarize_workload_health( deployments: dict[str, Any], statefulsets: dict[str, Any], daemonsets: dict[str, Any], ) -> dict[str, Any]: return { "deployments": deployments, "statefulsets": statefulsets, "daemonsets": daemonsets, } def _summarize_longhorn_volumes(payload: dict[str, Any]) -> dict[str, Any]: items = _items(payload) if not items: return {} by_state: dict[str, int] = {} by_robustness: dict[str, int] = {} degraded: list[dict[str, Any]] = [] attached_count = 0 detached_count = 0 degraded_count = 0 for volume in items: metadata = volume.get("metadata") if isinstance(volume.get("metadata"), dict) else {} status = volume.get("status") if isinstance(volume.get("status"), dict) else {} spec = volume.get("spec") if isinstance(volume.get("spec"), dict) else {} name = metadata.get("name") if isinstance(metadata.get("name"), str) else "" if not name: continue state = status.get("state") if isinstance(status.get("state"), str) else "unknown" robustness = ( status.get("robustness") if isinstance(status.get("robustness"), str) else "unknown" ) state_lower = state.lower() robustness_lower = robustness.lower() by_state[state] = by_state.get(state, 0) + 1 by_robustness[robustness] = by_robustness.get(robustness, 0) + 1 if state_lower == "attached": attached_count += 1 elif state_lower == "detached": detached_count += 1 if robustness_lower in {"degraded", "faulted"}: degraded_count += 1 degraded.append( { "name": name, "state": state, "robustness": robustness, "size": spec.get("size"), "actual_size": status.get("actualSize"), } ) degraded.sort(key=lambda item: item.get("name") or "") return { "total": len(items), "by_state": by_state, "by_robustness": by_robustness, "attached_count": attached_count, "detached_count": detached_count, "degraded": degraded, "degraded_count": degraded_count, } __all__ = [name for name in globals() if (name.startswith("_") and not name.startswith("__")) or name in {"ClusterStateSummary", "SignalContext"}]