Веб-UI кластера: страница деталей, kubectl по карточкам, мета 3 колонки
- Страница /cluster/<имя>: сводка, ресурсы узлов полосами, отдельные карточки на каждый kubectl get … -o json, рестарт пода. - API: overview с блоками k8s_*, POST pods/restart, расширенный набор ресурсов (-A). - Панель: спиннер загрузки, правки дашборда и стилей; документация api_routes, compose и прочие сопутствующие изменения.
This commit is contained in:
@@ -221,8 +221,8 @@ def aggregate_kind_cluster_resources(blocks: list[KindClusterResources]) -> Aggr
|
||||
cpu_l = f"ср. {av_cpu:.1f}%" if av_cpu is not None else "—"
|
||||
mem_l = f"ср. {av_mem_pct:.1f}%" if av_mem_pct is not None else "—"
|
||||
ratio_l = f"ср. {av_mem_ratio:.1f}%" if av_mem_ratio is not None else "—"
|
||||
net_l = f"Σ {_fmt_bytes_ru(sum_net)}" if sum_net > 0 else "—"
|
||||
disk_l = f"Σ {_fmt_bytes_ru(sum_blk)}" if sum_blk > 0 else "—"
|
||||
net_l = f"всего {_fmt_bytes_ru(sum_net)}" if sum_net > 0 else "—"
|
||||
disk_l = f"всего {_fmt_bytes_ru(sum_blk)}" if sum_blk > 0 else "—"
|
||||
|
||||
logger.debug(
|
||||
"aggregate_kind_cluster_resources: узлов=%s cpu_ring=%.1f net_ring=%.1f",
|
||||
@@ -322,3 +322,42 @@ def collect_kind_clusters_resource_stats() -> tuple[list[KindClusterResources],
|
||||
blocks.append(KindClusterResources(cluster_name=cluster_name, nodes=stats, note=None))
|
||||
|
||||
return blocks, None
|
||||
|
||||
|
||||
def collect_single_cluster_resource_stats(cluster_name: str) -> tuple[KindClusterResources, str | None]:
|
||||
"""
|
||||
Метрики узлов **одного** кластера (без полного прохода по всем kind-кластерам).
|
||||
|
||||
Если кластера нет в ``kind get clusters`` — пустой список узлов и пояснение в ``note``.
|
||||
"""
|
||||
name = cluster_name.strip()
|
||||
cli = _container_cli_bin()
|
||||
if not shutil.which(cli):
|
||||
return KindClusterResources(cluster_name=name, nodes=[], note=None), f"CLI «{cli}» не найден в PATH"
|
||||
|
||||
if name not in list_registered_kind_clusters():
|
||||
return KindClusterResources(
|
||||
cluster_name=name,
|
||||
nodes=[],
|
||||
note="Кластер не в списке kind — метрики контейнеров-узлов недоступны",
|
||||
), None
|
||||
|
||||
all_lines, ps_err = _all_container_names_ps_a(cli)
|
||||
if ps_err:
|
||||
return KindClusterResources(cluster_name=name, nodes=[], note=None), ps_err
|
||||
|
||||
running = _list_running_container_names(cli)
|
||||
prefix = f"{name}-"
|
||||
node_names = _sort_kind_node_containers([n for n in all_lines if n.startswith(prefix)])
|
||||
active = [n for n in node_names if n in running]
|
||||
if not active:
|
||||
return KindClusterResources(
|
||||
cluster_name=name,
|
||||
nodes=[],
|
||||
note="узлы остановлены или контейнеры отсутствуют",
|
||||
), None
|
||||
|
||||
stats = _stats_for_container_names(cli, active)
|
||||
order = {n: i for i, n in enumerate(node_names)}
|
||||
stats.sort(key=lambda s: order.get(s.container_name, 99))
|
||||
return KindClusterResources(cluster_name=name, nodes=stats, note=None), None
|
||||
|
||||
Reference in New Issue
Block a user