Kiali anonymous, журнал Helm, kubeconfig для контейнеров, UI аддонов
- Kiali: убран login, anonymous по умолчанию; удалены поля логина/пароля из UI и API - Журнал Helm: install/upgrade/delete, message и колонка в journal.js - Аддоны: values свёрнуты при подгрузке для установленных - GET …/kubeconfig/docker: host.docker.internal:порт + tls-server-name; кнопка в UI - apply_apiserver_endpoint_to_kubeconfig_file; KIND_K8S_APISERVER_GATEWAY_HOST в compose/env.example - README и api_routes.md обновлены
This commit is contained in:
@@ -464,7 +464,13 @@
|
||||
if (ta) ta.value = "";
|
||||
}
|
||||
|
||||
function showAddonValuesPanel(addon) {
|
||||
/**
|
||||
* Показать панель YAML values. Для установленного аддона при подгрузке values — блок <details> свёрнут.
|
||||
* @param {string} addon
|
||||
* @param {{ collapseDetails?: boolean } | undefined} opts
|
||||
*/
|
||||
function showAddonValuesPanel(addon, opts) {
|
||||
opts = opts || {};
|
||||
var pid = ADDON_VALUES_PANEL_ID[addon];
|
||||
if (!pid) return;
|
||||
var panel = document.getElementById(pid);
|
||||
@@ -472,6 +478,10 @@
|
||||
panel.classList.remove("hidden");
|
||||
panel.removeAttribute("hidden");
|
||||
panel.setAttribute("aria-hidden", "false");
|
||||
var det = panel.querySelector("details.cluster-addon-card__values-details");
|
||||
if (det) {
|
||||
det.open = opts.collapseDetails ? false : true;
|
||||
}
|
||||
}
|
||||
|
||||
function resetAllAddonValuesPanels() {
|
||||
@@ -532,7 +542,7 @@
|
||||
var t = document.getElementById("addons-values-yaml-" + addon);
|
||||
if (t) t.value = r.values_yaml || "";
|
||||
}
|
||||
showAddonValuesPanel(addon);
|
||||
showAddonValuesPanel(addon, { collapseDetails: addonEndpointInstalled(addon) });
|
||||
} catch (e) {
|
||||
setBootstrapMsg("Не удалось загрузить values (helm show values): " + e.message);
|
||||
} finally {
|
||||
@@ -674,7 +684,7 @@
|
||||
} else if (iv.ingress_nginx && iv.ingress_nginx.values_yaml) {
|
||||
var ti = document.getElementById("addons-values-yaml-ingress-nginx");
|
||||
if (ti) ti.value = iv.ingress_nginx.values_yaml;
|
||||
showAddonValuesPanel("ingress-nginx");
|
||||
showAddonValuesPanel("ingress-nginx", { collapseDetails: true });
|
||||
}
|
||||
|
||||
if (!st.kube_prometheus_stack) {
|
||||
@@ -682,7 +692,7 @@
|
||||
} else if (iv.kube_prometheus_stack && iv.kube_prometheus_stack.values_yaml) {
|
||||
var tp = document.getElementById("addons-values-yaml-kube-prometheus-stack");
|
||||
if (tp) tp.value = iv.kube_prometheus_stack.values_yaml;
|
||||
showAddonValuesPanel("kube-prometheus-stack");
|
||||
showAddonValuesPanel("kube-prometheus-stack", { collapseDetails: true });
|
||||
}
|
||||
|
||||
if (!st.metrics_server) {
|
||||
@@ -690,7 +700,7 @@
|
||||
} else if (iv.metrics_server && iv.metrics_server.values_yaml) {
|
||||
var tm = document.getElementById("addons-values-yaml-metrics-server");
|
||||
if (tm) tm.value = iv.metrics_server.values_yaml;
|
||||
showAddonValuesPanel("metrics-server");
|
||||
showAddonValuesPanel("metrics-server", { collapseDetails: true });
|
||||
}
|
||||
|
||||
if (!st.istio_mesh_ready) {
|
||||
@@ -710,7 +720,7 @@
|
||||
if (tiod) tiod.value = ik.istiod_values_yaml;
|
||||
}
|
||||
if (ik.kiali_values_yaml || ik.istio_base_values_yaml || ik.istiod_values_yaml) {
|
||||
showAddonValuesPanel("istio-kiali");
|
||||
showAddonValuesPanel("istio-kiali", { collapseDetails: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1002,17 +1012,9 @@
|
||||
return;
|
||||
}
|
||||
if (ep === "istio-kiali") {
|
||||
const u = document.getElementById("addons-kiali-user");
|
||||
const p = document.getElementById("addons-kiali-pass");
|
||||
const isel = document.getElementById("addons-istio-version-select");
|
||||
const ksel = document.getElementById("addons-kiali-version-select");
|
||||
const user = u ? u.value.trim() : "kiali-admin";
|
||||
const pw = p ? p.value : "";
|
||||
if (pw.length < 8) {
|
||||
alert("Задайте пароль Kiali не короче 8 символов.");
|
||||
return;
|
||||
}
|
||||
const payload = { kiali_username: user, kiali_password: pw };
|
||||
const payload = {};
|
||||
if (isel && isel.value.trim()) payload.istio_chart_version = isel.value.trim();
|
||||
if (ksel && ksel.value.trim()) payload.kiali_chart_version = ksel.value.trim();
|
||||
if (!attachAddonYamlToPayload(ep, payload)) return;
|
||||
|
||||
@@ -250,6 +250,20 @@
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Скачать kubeconfig для kubectl из другого контейнера: host.docker.internal:порт + tls-server-name (см. GET …/kubeconfig/docker).
|
||||
* @param {string} clusterName
|
||||
*/
|
||||
function downloadKubeconfigDocker(clusterName) {
|
||||
const url = API + "/clusters/" + encodeURIComponent(clusterName) + "/kubeconfig/docker";
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "kubeconfig-docker-" + clusterName + ".yaml";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
|
||||
/** SVG-иконки действий (stroke, currentColor). */
|
||||
var ICONS = {
|
||||
state:
|
||||
@@ -260,6 +274,9 @@
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5" y="5" width="14" height="14" rx="2"/></svg>',
|
||||
download:
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>',
|
||||
/** kubeconfig для контейнера: apiserver по имени control-plane в сети Docker */
|
||||
kubeDocker:
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>',
|
||||
trash:
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>',
|
||||
logFile:
|
||||
@@ -1519,7 +1536,7 @@
|
||||
iconActionButton(
|
||||
ICONS.download,
|
||||
c.has_local_kubeconfig
|
||||
? "Скачать kubeconfig для kubectl на хосте"
|
||||
? "Скачать kubeconfig для kubectl на хосте (localhost:порт)"
|
||||
: "Kubeconfig ещё нет — появится после создания или подъёма кластера",
|
||||
"icon-btn--secondary",
|
||||
c.has_local_kubeconfig
|
||||
@@ -1530,6 +1547,21 @@
|
||||
!c.has_local_kubeconfig,
|
||||
),
|
||||
);
|
||||
host.appendChild(
|
||||
iconActionButton(
|
||||
ICONS.kubeDocker,
|
||||
c.has_local_kubeconfig
|
||||
? "Скачать kubeconfig для kubectl из другого контейнера: host.docker.internal:порт + tls-server-name (как в веб-UI; на Linux — extra_hosts host-gateway)"
|
||||
: "Kubeconfig ещё нет — появится после создания или подъёма кластера",
|
||||
"icon-btn--secondary",
|
||||
c.has_local_kubeconfig
|
||||
? function () {
|
||||
downloadKubeconfigDocker(name);
|
||||
}
|
||||
: null,
|
||||
!c.has_local_kubeconfig,
|
||||
),
|
||||
);
|
||||
if (c.has_provision_log) {
|
||||
host.appendChild(
|
||||
iconActionButton(
|
||||
|
||||
@@ -88,6 +88,61 @@
|
||||
return "journal-status-pill";
|
||||
}
|
||||
|
||||
/** Суффикс job_kind (после helm_addon_install_|upgrade_|delete_) → id аддона в API. */
|
||||
function helmJobSlugToAddonId(slug) {
|
||||
const m = {
|
||||
ingress_nginx: "ingress-nginx",
|
||||
kube_prometheus_stack: "kube-prometheus-stack",
|
||||
metrics_server: "metrics-server",
|
||||
istio_kiali: "istio-kiali",
|
||||
};
|
||||
return m[slug] || String(slug || "").replace(/_/g, "-") || "—";
|
||||
}
|
||||
|
||||
function helmAddonTitle(id) {
|
||||
const m = {
|
||||
"ingress-nginx": "ingress-nginx",
|
||||
"kube-prometheus-stack": "kube-prometheus-stack",
|
||||
"metrics-server": "metrics-server",
|
||||
"istio-kiali": "Istio + Kiali",
|
||||
};
|
||||
return m[id] || id || "—";
|
||||
}
|
||||
|
||||
function helmOperationTitle(op) {
|
||||
const o = (op || "").toLowerCase();
|
||||
if (o === "install") return "Установка";
|
||||
if (o === "upgrade") return "Обновление";
|
||||
if (o === "delete") return "Удаление";
|
||||
return op || "—";
|
||||
}
|
||||
|
||||
/**
|
||||
* Колонка «Вид операции» для режима Helm: установка / обновление / удаление и имя аддона.
|
||||
* Старые записи без result.action разбираются по префиксу kind.
|
||||
*/
|
||||
function formatHelmJournalKind(e) {
|
||||
const r = e.result;
|
||||
if (r && typeof r === "object") {
|
||||
const verb = helmOperationTitle(r.action);
|
||||
const ad = r.addon != null ? helmAddonTitle(String(r.addon)) : "—";
|
||||
if (r.action && r.addon != null && String(r.addon).length) {
|
||||
return verb + " · " + ad;
|
||||
}
|
||||
}
|
||||
const k = e.kind || "";
|
||||
if (k.indexOf("helm_addon_delete_") === 0) {
|
||||
return "Удаление · " + helmAddonTitle(helmJobSlugToAddonId(k.replace(/^helm_addon_delete_/, "")));
|
||||
}
|
||||
if (k.indexOf("helm_addon_upgrade_") === 0) {
|
||||
return "Обновление · " + helmAddonTitle(helmJobSlugToAddonId(k.replace(/^helm_addon_upgrade_/, "")));
|
||||
}
|
||||
if (k.indexOf("helm_addon_install_") === 0) {
|
||||
return "Установка · " + helmAddonTitle(helmJobSlugToAddonId(k.replace(/^helm_addon_install_/, "")));
|
||||
}
|
||||
return k || "—";
|
||||
}
|
||||
|
||||
function visiblePageItems(current, total) {
|
||||
const delta = 2;
|
||||
const range = [];
|
||||
@@ -200,7 +255,7 @@
|
||||
const finished = formatUtc(
|
||||
e.finished_at_utc || e.created_at_utc,
|
||||
);
|
||||
const kind = e.kind || "";
|
||||
const kind = mode === "helm_addons" ? formatHelmJournalKind(e) : (e.kind || "");
|
||||
const msg = (e.message || "").trim();
|
||||
let lines = [];
|
||||
if (mode === "per_cluster") {
|
||||
|
||||
Reference in New Issue
Block a user