UI: карточка установленных аддонов на странице кластера; API аддонов и правки стилей

- Отдельная section.card после сводки ресурсов узлов, выравнивание бейджа Helm с заголовком
- Расширение эндпоинтов аддонов, схемы, helm_addons, cluster_addons.js/html
- Обновление api_routes.md
This commit is contained in:
Sergey Antropoff
2026-04-04 14:13:01 +03:00
parent eb063aec20
commit d55e69c756
9 changed files with 1238 additions and 229 deletions
+121
View File
@@ -1557,6 +1557,125 @@
bindActionTooltipHosts(host);
}
/**
* Скрыть секцию «Установленные аддоны» (#cluster-detail-addons-section) и очистить сетку.
*/
function clearClusterDetailAddonsStrip() {
var strip = document.getElementById("cluster-detail-addons-strip");
var section = document.getElementById("cluster-detail-addons-section");
if (strip) strip.replaceChildren();
if (section) {
section.classList.add("hidden");
section.setAttribute("hidden", "");
section.setAttribute("aria-hidden", "true");
}
}
/**
* Мини-карточки установленных Helm-аддонов в отдельной section.card под hero.
* @param {string} clusterName
* @param {object} st ответ GET /clusters/…/addons/status
*/
function renderClusterDetailAddonsStrip(clusterName, st) {
var strip = document.getElementById("cluster-detail-addons-strip");
var section = document.getElementById("cluster-detail-addons-section");
if (!strip || !section || !st) {
clearClusterDetailAddonsStrip();
return;
}
var items = [];
if (st.ingress_nginx) {
items.push({
title: "ingress-nginx",
ver: st.ingress_nginx_chart_version,
ns: "ingress-nginx",
});
}
if (st.kube_prometheus_stack) {
items.push({
title: "kube-prometheus-stack",
ver: st.kube_prometheus_stack_chart_version,
ns: "monitoring",
});
}
if (st.metrics_server) {
items.push({
title: "metrics-server",
ver: st.metrics_server_chart_version,
ns: "kube-system",
});
}
if (st.istio_mesh_ready) {
var iv = st.istiod_chart_version || st.istio_base_chart_version;
var kv = st.kiali_server_chart_version;
var parts = [];
if (iv) parts.push("Istio " + iv);
if (kv) parts.push("Kiali " + kv);
items.push({
title: "Istio + Kiali",
verLine: parts.length ? parts.join(" · ") : null,
ns: "istio-system",
});
}
strip.replaceChildren();
if (!items.length) {
section.classList.add("hidden");
section.setAttribute("hidden", "");
section.setAttribute("aria-hidden", "true");
return;
}
section.classList.remove("hidden");
section.removeAttribute("hidden");
section.setAttribute("aria-hidden", "false");
items.forEach(function (it) {
var a = document.createElement("a");
a.className = "cluster-detail-addon-mini";
a.href = "/cluster-addons";
a.setAttribute("role", "listitem");
a.setAttribute(
"title",
"Открыть страницу аддонов Helm; выберите кластер «" + clusterName + "» для настройки.",
);
var t = document.createElement("span");
t.className = "cluster-detail-addon-mini__title";
t.textContent = it.title;
a.appendChild(t);
var v = document.createElement("span");
v.className = "cluster-detail-addon-mini__ver";
if (it.verLine) {
v.textContent = it.verLine;
} else if (it.ver) {
v.textContent = "Чарт " + it.ver;
} else {
v.textContent = "Версия чарта не определена";
}
a.appendChild(v);
var n = document.createElement("span");
n.className = "cluster-detail-addon-mini__ns";
n.textContent = "ns: " + it.ns;
a.appendChild(n);
strip.appendChild(a);
});
}
/**
* Загрузить статус аддонов и обновить карточку «Установленные аддоны» (при наличии kubeconfig на диске).
* @param {string} clusterName
* @param {boolean} hasLocalKubeconfig
*/
async function refreshClusterDetailAddonsStrip(clusterName, hasLocalKubeconfig) {
if (!clusterName || !hasLocalKubeconfig) {
clearClusterDetailAddonsStrip();
return;
}
try {
var st = await api("/clusters/" + encodeURIComponent(clusterName) + "/addons/status");
renderClusterDetailAddonsStrip(clusterName, st);
} catch (e) {
clearClusterDetailAddonsStrip();
}
}
/**
* Загрузка ``GET /clusters/{name}/overview`` и заполнение блоков страницы кластера.
* @param {string} name
@@ -1578,6 +1697,7 @@
has_local_kubeconfig: !!d.has_local_kubeconfig,
has_provision_log: !!d.has_provision_log,
});
await refreshClusterDetailAddonsStrip(d.cluster_name, !!d.has_local_kubeconfig);
const cliRaw =
(cachedHealthPayload && cachedHealthPayload.container_cli) || "docker";
renderAggregateDonutsToRoot(
@@ -1611,6 +1731,7 @@
fillClusterK8sTablesFromOverview(d);
} catch (e) {
const errText = e && e.message ? e.message : String(e);
clearClusterDetailAddonsStrip();
if (msg) {
msg.textContent =
"Кластер или API недоступны: " +