Веб-интерфейс: страница /clusters, навигация и крошки для кластеров

- Выделена страница списка кластеров, панель упрощена; nav_active и крошки
  ведут в раздел Кластеры; theme.js синхронизирует активную пилюлю по URL.
- Доработки дашборда, аддонов, журнала, стилей и API-документации.
- Поддержка Podman: docker-compose.podman.yml, скрипты сокета; Makefile и env.
This commit is contained in:
Sergey Antropoff
2026-04-04 13:42:21 +03:00
parent 17f6233fd7
commit eb063aec20
38 changed files with 3990 additions and 734 deletions
+116 -3
View File
@@ -1,4 +1,4 @@
"""Справочник версий Helm-чартов для страницы аддонов (``helm search repo … --versions``).
"""Справочник версий Helm-чартов и сборка YAML values для редактора на странице аддонов.
Автор: Сергей Антропов
Сайт: https://devops.org.ru
@@ -11,14 +11,76 @@ import logging
from fastapi import APIRouter, HTTPException
from core.helm_addons import HelmAddonError, helm_addon_chart_versions_all, require_helm_binary
from models.schemas import HelmAddonChartVersionsResponse
from core.helm_addons import (
HelmAddonError,
compose_ingress_effective_values,
compose_istio_mesh_preview_values,
compose_kube_prometheus_effective_values,
compose_metrics_server_effective_values,
dump_helm_values_yaml,
helm_addon_chart_versions_all,
helm_repo_ensure,
require_helm_binary,
)
from models.schemas import (
HelmAddonChartVersionsResponse,
HelmAddonComposeBatchRequest,
HelmAddonComposeBatchResponse,
HelmAddonComposeValuesRequest,
HelmAddonComposeValuesResponse,
)
logger = logging.getLogger("kind_k8s.api.helm_charts")
router = APIRouter(tags=["helm-charts"])
def _compose_values_sync(req: HelmAddonComposeValuesRequest) -> HelmAddonComposeValuesResponse:
"""Синхронная сборка YAML (вызов из ``asyncio.to_thread``): ``helm show values`` + оверлеи."""
helm_repo_ensure()
addon = req.addon
if addon == "ingress-nginx":
data = compose_ingress_effective_values(req.chart_version)
return HelmAddonComposeValuesResponse(values_yaml=dump_helm_values_yaml(data))
if addon == "kube-prometheus-stack":
u = (req.grafana_admin_user or "admin").strip() or "admin"
pw = (req.grafana_admin_password or "").strip() or "ChangeMe12345"
data = compose_kube_prometheus_effective_values(req.chart_version, u, pw)
return HelmAddonComposeValuesResponse(values_yaml=dump_helm_values_yaml(data))
if addon == "metrics-server":
data = compose_metrics_server_effective_values(req.chart_version)
return HelmAddonComposeValuesResponse(values_yaml=dump_helm_values_yaml(data))
if addon == "istio-kiali":
k, ib, ir = compose_istio_mesh_preview_values(req.istio_chart_version, req.kiali_chart_version)
return HelmAddonComposeValuesResponse(
values_yaml=dump_helm_values_yaml(k),
istio_base_values_yaml=dump_helm_values_yaml(ib),
istio_istiod_values_yaml=dump_helm_values_yaml(ir),
)
raise RuntimeError(f"неизвестный addon: {addon}")
def _compose_batch_sync(body: HelmAddonComposeBatchRequest) -> HelmAddonComposeBatchResponse:
"""Один ``helm repo update`` и шесть выводов ``helm show values`` (с оверлеями где нужно)."""
helm_repo_ensure()
u = (body.grafana_admin_user or "admin").strip() or "admin"
pw = (body.grafana_admin_password or "").strip() or "ChangeMe12345"
ing = dump_helm_values_yaml(compose_ingress_effective_values(body.ingress_chart_version))
prom = dump_helm_values_yaml(
compose_kube_prometheus_effective_values(body.kube_prometheus_chart_version, u, pw),
)
ms = dump_helm_values_yaml(compose_metrics_server_effective_values(body.metrics_server_chart_version))
k, ib, ir = compose_istio_mesh_preview_values(body.istio_chart_version, body.kiali_chart_version)
return HelmAddonComposeBatchResponse(
ingress_nginx_values_yaml=ing,
kube_prometheus_values_yaml=prom,
metrics_server_values_yaml=ms,
kiali_values_yaml=dump_helm_values_yaml(k),
istio_base_values_yaml=dump_helm_values_yaml(ib),
istio_istiod_values_yaml=dump_helm_values_yaml(ir),
)
@router.get(
"/helm/chart-versions",
response_model=HelmAddonChartVersionsResponse,
@@ -42,3 +104,54 @@ async def get_helm_addon_chart_versions() -> HelmAddonChartVersionsResponse:
logger.exception("Ошибка получения версий чартов")
raise HTTPException(status_code=500, detail=str(e)) from e
return HelmAddonChartVersionsResponse(**data)
@router.post(
"/helm/addons/compose-values",
response_model=HelmAddonComposeValuesResponse,
summary="Собрать YAML values для редактора аддонов (helm show values + форма)",
)
async def post_helm_addon_compose_values(
body: HelmAddonComposeValuesRequest,
) -> HelmAddonComposeValuesResponse:
"""
Выполняет ``helm repo update`` (внутри compose-функций) и ``helm show values`` для выбранного аддона.
Для **kube-prometheus-stack** в YAML подставляются логин и пароль Grafana из тела запроса;
если пароль пуст, в preview используется временная строка ``ChangeMe12345`` (замените перед установкой).
Для **istio-kiali** возвращаются три блока YAML: **kiali-server**, **istio/base**, **istio/istiod**.
"""
try:
require_helm_binary()
except HelmAddonError as e:
raise HTTPException(status_code=503, detail=str(e)) from e
try:
return await asyncio.to_thread(_compose_values_sync, body)
except HelmAddonError as e:
logger.exception("compose-values: ошибка helm")
raise HTTPException(status_code=500, detail=str(e)) from e
@router.post(
"/helm/addons/compose-values-batch",
response_model=HelmAddonComposeBatchResponse,
summary="Собрать все YAML values для страницы аддонов одним запросом",
)
async def post_helm_addon_compose_values_batch(
body: HelmAddonComposeBatchRequest,
) -> HelmAddonComposeBatchResponse:
"""
Один проход **``helm repo update``** и подстановка версий из селектов / полей формы на странице аддонов.
Удобнее, чем четыре отдельных **compose-values**, когда UI обновляет все карточки сразу.
"""
try:
require_helm_binary()
except HelmAddonError as e:
raise HTTPException(status_code=503, detail=str(e)) from e
try:
return await asyncio.to_thread(_compose_batch_sync, body)
except HelmAddonError as e:
logger.exception("compose-values-batch: ошибка helm")
raise HTTPException(status_code=500, detail=str(e)) from e