Веб-интерфейс: страница /clusters, навигация и крошки для кластеров
- Выделена страница списка кластеров, панель упрощена; nav_active и крошки ведут в раздел Кластеры; theme.js синхронизирует активную пилюлю по URL. - Доработки дашборда, аддонов, журнала, стилей и API-документации. - Поддержка Podman: docker-compose.podman.yml, скрипты сокета; Makefile и env.
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
{# Прокрутка только у пилюль: overflow-x на nav обрезал бы выпадающее меню API (position: absolute). #}
|
||||
<div class="nav-links-scroll">
|
||||
<a href="/" class="nav-link nav-pill{% if nav_active|default('') == 'panel' %} nav-pill--active{% endif %}">Панель</a>
|
||||
<a href="/clusters" class="nav-link nav-pill{% if nav_active|default('') == 'clusters' %} nav-pill--active{% endif %}">Кластеры</a>
|
||||
<a href="/cluster-addons" class="nav-link nav-pill{% if nav_active|default('') == 'cluster_addons' %} nav-pill--active{% endif %}">Аддоны</a>
|
||||
<a href="/journal" class="nav-link nav-pill{% if nav_active|default('') == 'journal' %} nav-pill--active{% endif %}">Журнал</a>
|
||||
<a href="/documentation" class="nav-link nav-pill{% if nav_active|default('') == 'documentation' %} nav-pill--active{% endif %}">Документация</a>
|
||||
|
||||
@@ -38,46 +38,66 @@
|
||||
<h1 class="page-title" id="addons-hero-title">Дополнения кластера (Helm)</h1>
|
||||
<p class="muted page-lead">
|
||||
Выберите кластер с сохранённым kubeconfig. Установка и удаление выполняются через <code>helm</code> в контейнере веб-приложения;
|
||||
операции могут занимать несколько минут — дождитесь ответа сервера. Для kind у ingress-nginx задан NodePort <strong>30080</strong>.
|
||||
операции могут занимать несколько минут — ход и вывод команд отображаются в журнале ниже (как при развёртывании кластера). История операций сохраняется в каталоге кластера.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="card create-cluster-card cluster-addons-toolbar-card">
|
||||
<h2 class="create-cluster-card__title">Кластер</h2>
|
||||
<div class="cluster-addons-cluster-row">
|
||||
<label for="addons-cluster-select" class="cluster-addons-cluster-label">Активный кластер</label>
|
||||
<select id="addons-cluster-select" class="cluster-addons-cluster-select" aria-describedby="addons-cluster-hint">
|
||||
<label for="addons-cluster-select" class="cluster-addons-cluster-label">Выберите кластер для просмотра статуса аддонов.</label>
|
||||
<select id="addons-cluster-select" class="cluster-addons-cluster-select" aria-label="Выберите кластер для просмотра статуса аддонов">
|
||||
<option value="">— загрузка списка —</option>
|
||||
</select>
|
||||
<button type="button" class="btn-secondary" id="addons-refresh-status">Обновить статус</button>
|
||||
</div>
|
||||
<p id="addons-cluster-hint" class="muted cluster-addons-hint">
|
||||
Нужен файл <code>clusters/<имя>/kubeconfig</code> и доступ API из контейнера.
|
||||
</p>
|
||||
<p id="addons-versions-hint" class="muted cluster-addons-hint">
|
||||
Список версий чартов подгружается с сервера (<code>GET /api/v1/helm/chart-versions</code>); значение «Последняя» не передаёт <code>--version</code> в Helm.
|
||||
</p>
|
||||
<div id="addons-status-bar" class="cluster-addons-status-bar muted" role="status" aria-live="polite"></div>
|
||||
<div id="addons-status-bar" class="cluster-addons-status-bar" role="status" aria-live="polite"></div>
|
||||
<p id="addons-bootstrap-msg" class="cluster-addons-bootstrap-msg muted hidden" role="status" aria-live="polite"></p>
|
||||
</section>
|
||||
|
||||
<div
|
||||
id="addons-cards-wrap"
|
||||
class="cluster-addons-cards-wrap hidden"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="cluster-addons-grid">
|
||||
<section class="card cluster-addon-card" data-addon="ingress-nginx">
|
||||
<h2 class="cluster-addon-card__title">ingress-nginx</h2>
|
||||
<p class="muted cluster-addon-card__desc">Контроллер Ingress; для kind: NodePort HTTP на порту 30080.</p>
|
||||
<header class="cluster-addon-card__header">
|
||||
<h2 class="cluster-addon-card__title">ingress-nginx</h2>
|
||||
<span class="cluster-addon-card__badge cluster-addon-card__badge--off" role="status">Не установлен</span>
|
||||
</header>
|
||||
<p class="muted cluster-addon-card__desc">Контроллер Ingress.</p>
|
||||
<div class="create-form-field">
|
||||
<label for="addons-ing-version-select">Версия чарта</label>
|
||||
<select id="addons-ing-version-select" class="cluster-addons-version-select" aria-describedby="addons-versions-hint">
|
||||
<select id="addons-ing-version-select" class="cluster-addons-version-select" aria-label="Версия чарта ingress-nginx">
|
||||
<option value="">Последняя (из репозитория)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="cluster-addon-card__actions row">
|
||||
<details class="cluster-addon-card__values-details">
|
||||
<summary class="cluster-addon-card__values-summary">Values чарта (YAML)</summary>
|
||||
<p class="muted cluster-addon-card__values-hint">
|
||||
Содержимое из <code>helm show values</code> плюс сервис для kind; подставляется при смене версии чарта. После <code>-f</code> Helm применяет <code>--set</code> для NodePort.
|
||||
</p>
|
||||
<label for="addons-values-yaml-ingress-nginx" class="sr-only">Полные YAML values для ingress-nginx</label>
|
||||
<textarea
|
||||
id="addons-values-yaml-ingress-nginx"
|
||||
class="cluster-addon-card__values-textarea mono"
|
||||
rows="12"
|
||||
spellcheck="false"
|
||||
aria-label="Полные YAML values чарта ingress-nginx"
|
||||
></textarea>
|
||||
</details>
|
||||
<div class="cluster-addon-card__actions row cluster-addon-card__actions--equal">
|
||||
<button type="button" class="btn-addon-install" data-endpoint="ingress-nginx">Установить</button>
|
||||
<button type="button" class="btn-secondary btn-addon-remove" data-endpoint="ingress-nginx">Удалить</button>
|
||||
<button type="button" class="btn-secondary btn-addon-remove hidden" data-endpoint="ingress-nginx" hidden>Удалить</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-addon-card" data-addon="kube-prometheus-stack">
|
||||
<h2 class="cluster-addon-card__title">kube-prometheus-stack</h2>
|
||||
<header class="cluster-addon-card__header">
|
||||
<h2 class="cluster-addon-card__title">kube-prometheus-stack</h2>
|
||||
<span class="cluster-addon-card__badge cluster-addon-card__badge--off" role="status">Не установлен</span>
|
||||
</header>
|
||||
<p class="muted cluster-addon-card__desc">Prometheus Operator, Alertmanager, Grafana.</p>
|
||||
<div class="create-form-field">
|
||||
<label for="addons-grafana-user">Логин администратора Grafana</label>
|
||||
@@ -93,14 +113,31 @@
|
||||
<option value="">Последняя (из репозитория)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="cluster-addon-card__actions row">
|
||||
<details class="cluster-addon-card__values-details">
|
||||
<summary class="cluster-addon-card__values-summary">Values чарта (YAML)</summary>
|
||||
<p class="muted cluster-addon-card__values-hint">
|
||||
Вывод <code>helm show values</code> с подставленными логином и паролем Grafana из полей выше; обновляется при смене версии или учётных данных. Пустое поле при установке — сервер соберёт values сам.
|
||||
</p>
|
||||
<label for="addons-values-yaml-kube-prometheus-stack" class="sr-only">Полные YAML values для kube-prometheus-stack</label>
|
||||
<textarea
|
||||
id="addons-values-yaml-kube-prometheus-stack"
|
||||
class="cluster-addon-card__values-textarea mono"
|
||||
rows="12"
|
||||
spellcheck="false"
|
||||
aria-label="Полные YAML values чарта kube-prometheus-stack"
|
||||
></textarea>
|
||||
</details>
|
||||
<div class="cluster-addon-card__actions row cluster-addon-card__actions--equal">
|
||||
<button type="button" class="btn-addon-install" data-endpoint="kube-prometheus-stack">Установить</button>
|
||||
<button type="button" class="btn-secondary btn-addon-remove" data-endpoint="kube-prometheus-stack">Удалить</button>
|
||||
<button type="button" class="btn-secondary btn-addon-remove hidden" data-endpoint="kube-prometheus-stack" hidden>Удалить</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-addon-card" data-addon="metrics-server">
|
||||
<h2 class="cluster-addon-card__title">metrics-server</h2>
|
||||
<header class="cluster-addon-card__header">
|
||||
<h2 class="cluster-addon-card__title">metrics-server</h2>
|
||||
<span class="cluster-addon-card__badge cluster-addon-card__badge--off" role="status">Не установлен</span>
|
||||
</header>
|
||||
<p class="muted cluster-addon-card__desc">Метрики узлов и подов для <code>kubectl top</code>; для kind включён <code>--kubelet-insecure-tls</code>.</p>
|
||||
<div class="create-form-field">
|
||||
<label for="addons-ms-version-select">Версия чарта</label>
|
||||
@@ -108,14 +145,31 @@
|
||||
<option value="">Последняя (из репозитория)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="cluster-addon-card__actions row">
|
||||
<details class="cluster-addon-card__values-details">
|
||||
<summary class="cluster-addon-card__values-summary">Values чарта (YAML)</summary>
|
||||
<p class="muted cluster-addon-card__values-hint">
|
||||
<code>helm show values</code> плюс аргументы для kind (<code>--kubelet-insecure-tls</code> и т.д.). Пустое поле — автосборка на сервере.
|
||||
</p>
|
||||
<label for="addons-values-yaml-metrics-server" class="sr-only">Полные YAML values для metrics-server</label>
|
||||
<textarea
|
||||
id="addons-values-yaml-metrics-server"
|
||||
class="cluster-addon-card__values-textarea mono"
|
||||
rows="12"
|
||||
spellcheck="false"
|
||||
aria-label="Полные YAML values чарта metrics-server"
|
||||
></textarea>
|
||||
</details>
|
||||
<div class="cluster-addon-card__actions row cluster-addon-card__actions--equal">
|
||||
<button type="button" class="btn-addon-install" data-endpoint="metrics-server">Установить</button>
|
||||
<button type="button" class="btn-secondary btn-addon-remove" data-endpoint="metrics-server">Удалить</button>
|
||||
<button type="button" class="btn-secondary btn-addon-remove hidden" data-endpoint="metrics-server" hidden>Удалить</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-addon-card cluster-addon-card--wide" data-addon="istio-kiali">
|
||||
<h2 class="cluster-addon-card__title">Istio + Kiali</h2>
|
||||
<header class="cluster-addon-card__header">
|
||||
<h2 class="cluster-addon-card__title">Istio + Kiali</h2>
|
||||
<span class="cluster-addon-card__badge cluster-addon-card__badge--off" role="status">Не установлен</span>
|
||||
</header>
|
||||
<p class="muted cluster-addon-card__desc">
|
||||
Чарты <code>istio/base</code>, <code>istio/istiod</code> и <code>kiali-server</code> в <code>istio-system</code>. Вход в Kiali — стратегия
|
||||
<strong>login</strong> (секрет с логином и паролем).
|
||||
@@ -142,32 +196,83 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cluster-addon-card__actions row">
|
||||
<details class="cluster-addon-card__values-details">
|
||||
<summary class="cluster-addon-card__values-summary">Values чартов Istio и Kiali (YAML)</summary>
|
||||
<p class="muted cluster-addon-card__values-hint">
|
||||
Три блока из <code>helm show values</code> для выбранных версий. Логин и пароль Kiali вносятся в секрет Kubernetes отдельно; для kiali-server дополнительно задаётся <code>auth.strategy=login</code> через <code>--set</code>.
|
||||
</p>
|
||||
<p class="cluster-addon-card__values-subhead">kiali-server</p>
|
||||
<label for="addons-values-yaml-istio-kiali" class="sr-only">YAML values kiali-server</label>
|
||||
<textarea
|
||||
id="addons-values-yaml-istio-kiali"
|
||||
class="cluster-addon-card__values-textarea mono"
|
||||
rows="10"
|
||||
spellcheck="false"
|
||||
aria-label="Полные YAML values чарта kiali-server"
|
||||
></textarea>
|
||||
<p class="cluster-addon-card__values-subhead">istio/base</p>
|
||||
<label for="addons-values-yaml-istio-base" class="sr-only">YAML values istio-base</label>
|
||||
<textarea
|
||||
id="addons-values-yaml-istio-base"
|
||||
class="cluster-addon-card__values-textarea mono"
|
||||
rows="10"
|
||||
spellcheck="false"
|
||||
aria-label="Полные YAML values чарта istio/base"
|
||||
></textarea>
|
||||
<p class="cluster-addon-card__values-subhead">istio/istiod</p>
|
||||
<label for="addons-values-yaml-istio-istiod" class="sr-only">YAML values istiod</label>
|
||||
<textarea
|
||||
id="addons-values-yaml-istio-istiod"
|
||||
class="cluster-addon-card__values-textarea mono"
|
||||
rows="10"
|
||||
spellcheck="false"
|
||||
aria-label="Полные YAML values чарта istio/istiod"
|
||||
></textarea>
|
||||
</details>
|
||||
<div class="cluster-addon-card__actions row cluster-addon-card__actions--equal">
|
||||
<button type="button" class="btn-addon-install" data-endpoint="istio-kiali">Установить</button>
|
||||
<button type="button" class="btn-secondary btn-addon-remove" data-endpoint="istio-kiali">Удалить</button>
|
||||
<button type="button" class="btn-secondary btn-addon-remove hidden" data-endpoint="istio-kiali" hidden>Удалить</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="card cluster-addons-log-card">
|
||||
<h2 class="create-cluster-card__title">Журнал последней операции</h2>
|
||||
<pre id="addons-log-pre" class="mono cluster-addons-log-pre" role="log" aria-live="polite"></pre>
|
||||
{# Журнал операции Helm: те же блоки, что на странице создания кластера (прогресс + job-log-panel). Без полноэкранного спиннера. #}
|
||||
<section
|
||||
id="addons-helm-progress-wrap"
|
||||
class="card create-progress-wrap cluster-addons-helm-progress hidden"
|
||||
aria-hidden="true"
|
||||
aria-labelledby="addons-helm-progress-title"
|
||||
>
|
||||
<h2 class="create-cluster-card__title" id="addons-helm-progress-title">Ход операции Helm</h2>
|
||||
<p class="create-progress-hint muted" id="addons-helm-progress-hint">
|
||||
Выполняется команда в контейнере веб-приложения; полный вывод появится по завершении.
|
||||
</p>
|
||||
<div
|
||||
class="progress-track"
|
||||
role="progressbar"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
aria-valuenow="0"
|
||||
aria-labelledby="addons-helm-progress-label"
|
||||
id="addons-helm-progress-track"
|
||||
>
|
||||
<div class="progress-bar" id="addons-helm-progress-bar" style="width: 0%"></div>
|
||||
</div>
|
||||
<p class="progress-label" id="addons-helm-progress-label">—</p>
|
||||
<div class="job-log-panel-wrap">
|
||||
<label for="addons-helm-log-panel" class="job-log-label muted">Журнал установки / удаления</label>
|
||||
<pre
|
||||
id="addons-helm-log-panel"
|
||||
class="mono job-log-panel"
|
||||
role="log"
|
||||
aria-live="polite"
|
||||
aria-relevant="additions"
|
||||
></pre>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div
|
||||
id="addons-busy-overlay"
|
||||
class="page-loading-overlay cluster-addons-busy-overlay hidden"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-busy="false"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="page-loading-backdrop" aria-hidden="true"></div>
|
||||
<div class="page-loading-center">
|
||||
<span class="spinner page-loading-spinner" aria-hidden="true"></span>
|
||||
<span id="addons-busy-label" class="page-loading-label">Выполняется операция Helm…</span>
|
||||
</div>
|
||||
</div>
|
||||
{% include "partials/dashboard_modals.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
||||
@@ -119,16 +119,18 @@
|
||||
<section class="card jobs-card">
|
||||
<div class="row spread jobs-card-toolbar">
|
||||
<h2 id="jobs-heading" class="jobs-card-title">Последние задания</h2>
|
||||
<button type="button" id="btn-jobs-clear" class="btn-secondary">Очистить завершённые</button>
|
||||
<button type="button" id="btn-jobs-refresh" class="btn-secondary">Обновить</button>
|
||||
</div>
|
||||
<div class="table-wrap">
|
||||
<table id="tbl-jobs" aria-label="Последние задания создания">
|
||||
<div class="table-wrap journal-table-wrap">
|
||||
<table id="tbl-jobs" class="journal-table" aria-label="Последние задания из журналов кластеров">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Дата, время <span class="th-hint">(UTC)</span></th>
|
||||
<th>Кластер</th>
|
||||
<th>Статус</th>
|
||||
<th>Сообщение</th>
|
||||
<th scope="col">Завершено (UTC)</th>
|
||||
<th scope="col">Кластер</th>
|
||||
<th scope="col">Тип задания</th>
|
||||
<th scope="col">Статус</th>
|
||||
<th scope="col">Сообщение</th>
|
||||
<th scope="col">Лог</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</div>
|
||||
|
||||
<p class="cluster-detail-breadcrumb muted" aria-label="Навигация">
|
||||
<a href="/">Панель</a>
|
||||
<a href="/clusters">Кластеры</a>
|
||||
<span aria-hidden="true"> / </span>
|
||||
<span>Кластер <code>{{ cluster_name | e }}</code></span>
|
||||
</p>
|
||||
@@ -78,7 +78,9 @@
|
||||
<h2 id="cluster-k8s-heading" class="cluster-detail-section-title">Kubernetes (kubectl)</h2>
|
||||
<p class="muted cluster-k8s-scope-hint">
|
||||
Данные по <strong>всему кластеру</strong>: ресурсы в namespace — со всех пространств имён; узлы и список
|
||||
namespace — без ограничения по отдельному ns.
|
||||
namespace — без ограничения по отдельному ns. В карточках ресурсов выпадающий список справа от заголовка
|
||||
содержит все namespace из ответа API и из фактических объектов в таблицах; при выборе «Все namespace» строки
|
||||
таблицы упорядочены по namespace, затем по имени ресурса.
|
||||
</p>
|
||||
<p id="cluster-kube-global-hint" class="muted cluster-kube-hint hidden" role="status"></p>
|
||||
</section>
|
||||
@@ -94,52 +96,182 @@
|
||||
</section>
|
||||
|
||||
<section class="card cluster-k8s-resource-card" aria-labelledby="k8s-pods-title">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-pods-title">Поды</h2>
|
||||
<div class="cluster-k8s-card-header">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-pods-title">Поды</h2>
|
||||
<div class="cluster-k8s-ns-filter-wrap">
|
||||
<label for="cluster-k8s-filter-pods" class="sr-only">Поды: фильтр по namespace</label>
|
||||
<select
|
||||
id="cluster-k8s-filter-pods"
|
||||
class="cluster-k8s-ns-select"
|
||||
data-cluster-k8s-ns-filter="pods"
|
||||
aria-label="Поды: фильтр по namespace"
|
||||
>
|
||||
<option value="">Все namespace</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster-k8s-pods-root" class="cluster-k8s-root" role="region" aria-label="Поды"></div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-k8s-resource-card" aria-labelledby="k8s-deploy-title">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-deploy-title">Deployments</h2>
|
||||
<div class="cluster-k8s-card-header">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-deploy-title">Deployments</h2>
|
||||
<div class="cluster-k8s-ns-filter-wrap">
|
||||
<label for="cluster-k8s-filter-deployments" class="sr-only">Deployments: фильтр по namespace</label>
|
||||
<select
|
||||
id="cluster-k8s-filter-deployments"
|
||||
class="cluster-k8s-ns-select"
|
||||
data-cluster-k8s-ns-filter="deployments"
|
||||
aria-label="Deployments: фильтр по namespace"
|
||||
>
|
||||
<option value="">Все namespace</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster-k8s-deployments-root" class="cluster-k8s-root" role="region"></div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-k8s-resource-card" aria-labelledby="k8s-sts-title">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-sts-title">StatefulSets</h2>
|
||||
<div class="cluster-k8s-card-header">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-sts-title">StatefulSets</h2>
|
||||
<div class="cluster-k8s-ns-filter-wrap">
|
||||
<label for="cluster-k8s-filter-statefulsets" class="sr-only">StatefulSets: фильтр по namespace</label>
|
||||
<select
|
||||
id="cluster-k8s-filter-statefulsets"
|
||||
class="cluster-k8s-ns-select"
|
||||
data-cluster-k8s-ns-filter="statefulsets"
|
||||
aria-label="StatefulSets: фильтр по namespace"
|
||||
>
|
||||
<option value="">Все namespace</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster-k8s-statefulsets-root" class="cluster-k8s-root" role="region"></div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-k8s-resource-card" aria-labelledby="k8s-ds-title">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-ds-title">DaemonSets</h2>
|
||||
<div class="cluster-k8s-card-header">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-ds-title">DaemonSets</h2>
|
||||
<div class="cluster-k8s-ns-filter-wrap">
|
||||
<label for="cluster-k8s-filter-daemonsets" class="sr-only">DaemonSets: фильтр по namespace</label>
|
||||
<select
|
||||
id="cluster-k8s-filter-daemonsets"
|
||||
class="cluster-k8s-ns-select"
|
||||
data-cluster-k8s-ns-filter="daemonsets"
|
||||
aria-label="DaemonSets: фильтр по namespace"
|
||||
>
|
||||
<option value="">Все namespace</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster-k8s-daemonsets-root" class="cluster-k8s-root" role="region"></div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-k8s-resource-card" aria-labelledby="k8s-rs-title">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-rs-title">ReplicaSets</h2>
|
||||
<div class="cluster-k8s-card-header">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-rs-title">ReplicaSets</h2>
|
||||
<div class="cluster-k8s-ns-filter-wrap">
|
||||
<label for="cluster-k8s-filter-replicasets" class="sr-only">ReplicaSets: фильтр по namespace</label>
|
||||
<select
|
||||
id="cluster-k8s-filter-replicasets"
|
||||
class="cluster-k8s-ns-select"
|
||||
data-cluster-k8s-ns-filter="replicasets"
|
||||
aria-label="ReplicaSets: фильтр по namespace"
|
||||
>
|
||||
<option value="">Все namespace</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster-k8s-replicasets-root" class="cluster-k8s-root" role="region"></div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-k8s-resource-card" aria-labelledby="k8s-jobs-title">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-jobs-title">Jobs</h2>
|
||||
<div class="cluster-k8s-card-header">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-jobs-title">Jobs</h2>
|
||||
<div class="cluster-k8s-ns-filter-wrap">
|
||||
<label for="cluster-k8s-filter-jobs" class="sr-only">Jobs: фильтр по namespace</label>
|
||||
<select
|
||||
id="cluster-k8s-filter-jobs"
|
||||
class="cluster-k8s-ns-select"
|
||||
data-cluster-k8s-ns-filter="jobs"
|
||||
aria-label="Jobs: фильтр по namespace"
|
||||
>
|
||||
<option value="">Все namespace</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster-k8s-jobs-root" class="cluster-k8s-root" role="region"></div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-k8s-resource-card" aria-labelledby="k8s-cj-title">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-cj-title">CronJobs</h2>
|
||||
<div class="cluster-k8s-card-header">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-cj-title">CronJobs</h2>
|
||||
<div class="cluster-k8s-ns-filter-wrap">
|
||||
<label for="cluster-k8s-filter-cronjobs" class="sr-only">CronJobs: фильтр по namespace</label>
|
||||
<select
|
||||
id="cluster-k8s-filter-cronjobs"
|
||||
class="cluster-k8s-ns-select"
|
||||
data-cluster-k8s-ns-filter="cronjobs"
|
||||
aria-label="CronJobs: фильтр по namespace"
|
||||
>
|
||||
<option value="">Все namespace</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster-k8s-cronjobs-root" class="cluster-k8s-root" role="region"></div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-k8s-resource-card" aria-labelledby="k8s-svc-title">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-svc-title">Сервисы</h2>
|
||||
<div class="cluster-k8s-card-header">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-svc-title">Сервисы</h2>
|
||||
<div class="cluster-k8s-ns-filter-wrap">
|
||||
<label for="cluster-k8s-filter-services" class="sr-only">Сервисы: фильтр по namespace</label>
|
||||
<select
|
||||
id="cluster-k8s-filter-services"
|
||||
class="cluster-k8s-ns-select"
|
||||
data-cluster-k8s-ns-filter="services"
|
||||
aria-label="Сервисы: фильтр по namespace"
|
||||
>
|
||||
<option value="">Все namespace</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster-k8s-services-root" class="cluster-k8s-root" role="region"></div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-k8s-resource-card" aria-labelledby="k8s-ing-title">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-ing-title">Ingresses</h2>
|
||||
<div class="cluster-k8s-card-header">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-ing-title">Ingresses</h2>
|
||||
<div class="cluster-k8s-ns-filter-wrap">
|
||||
<label for="cluster-k8s-filter-ingresses" class="sr-only">Ingresses: фильтр по namespace</label>
|
||||
<select
|
||||
id="cluster-k8s-filter-ingresses"
|
||||
class="cluster-k8s-ns-select"
|
||||
data-cluster-k8s-ns-filter="ingresses"
|
||||
aria-label="Ingresses: фильтр по namespace"
|
||||
>
|
||||
<option value="">Все namespace</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster-k8s-ingresses-root" class="cluster-k8s-root" role="region"></div>
|
||||
</section>
|
||||
|
||||
<section class="card cluster-k8s-resource-card" aria-labelledby="k8s-pvc-title">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-pvc-title">PVC</h2>
|
||||
<div class="cluster-k8s-card-header">
|
||||
<h2 class="cluster-detail-section-title" id="k8s-pvc-title">PVC</h2>
|
||||
<div class="cluster-k8s-ns-filter-wrap">
|
||||
<label for="cluster-k8s-filter-pvcs" class="sr-only">PVC: фильтр по namespace</label>
|
||||
<select
|
||||
id="cluster-k8s-filter-pvcs"
|
||||
class="cluster-k8s-ns-select"
|
||||
data-cluster-k8s-ns-filter="pvcs"
|
||||
aria-label="PVC: фильтр по namespace"
|
||||
>
|
||||
<option value="">Все namespace</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cluster-k8s-pvcs-root" class="cluster-k8s-root" role="region" aria-label="PersistentVolumeClaim"></div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
{% block content %}
|
||||
<p class="cluster-detail-breadcrumb muted" aria-label="Навигация">
|
||||
<a href="/">Панель</a>
|
||||
<a href="/clusters">Кластеры</a>
|
||||
<span aria-hidden="true"> / </span>
|
||||
<a href="/cluster/{{ cluster_name }}">Кластер <code>{{ cluster_name | e }}</code></a>
|
||||
<span aria-hidden="true"> / </span>
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
{# Список кластеров и сводка ресурсов узлов (перенесено с панели).
|
||||
Автор: Сергей Антропов — https://devops.org.ru #}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block page_title %}Кластеры{% endblock %}
|
||||
|
||||
{% block body_extra_class %} dashboard-clusters-loading{% endblock %}
|
||||
|
||||
{% block body_attrs %}data-dashboard-mode="clusters"{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
<div class="footer-inner">
|
||||
<p class="footer-copyright">
|
||||
© {{ app_title }} ·
|
||||
<a href="https://devops.org.ru" target="_blank" rel="noopener">devops.org.ru</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div
|
||||
id="clusters-page-loading-overlay"
|
||||
class="page-loading-overlay"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-busy="true"
|
||||
aria-label="Загрузка списка кластеров"
|
||||
>
|
||||
<div class="page-loading-backdrop" aria-hidden="true"></div>
|
||||
<div class="page-loading-center">
|
||||
<span class="spinner page-loading-spinner" aria-hidden="true"></span>
|
||||
<span class="page-loading-label">Загрузка кластеров и метрик узлов…</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="card hero-panel clusters-page-hero" aria-labelledby="clusters-page-title">
|
||||
<div class="clusters-page-hero-row">
|
||||
<div class="clusters-page-hero-text">
|
||||
<h1 class="page-title" id="clusters-page-title">Кластеры</h1>
|
||||
<p class="muted page-lead clusters-page-hero-lead">
|
||||
Запущенные узлы kind, kubeconfig и действия.
|
||||
</p>
|
||||
</div>
|
||||
<div class="clusters-page-hero-actions">
|
||||
<a href="/cluster-create" class="clusters-page-create-btn">Создать кластер</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="aggregate-donuts-section" class="card aggregate-donuts-card" aria-labelledby="donuts-heading">
|
||||
<h2 id="donuts-heading" class="donuts-card-title">Ресурсы узлов (сводка)</h2>
|
||||
<div id="aggregate-donuts" class="aggregate-donuts" aria-live="polite"></div>
|
||||
</section>
|
||||
|
||||
<section class="card clusters-card">
|
||||
<h2>Список кластеров</h2>
|
||||
<div class="table-wrap">
|
||||
<table id="tbl-clusters" aria-label="Список кластеров">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-cluster-name">Имя</th>
|
||||
<th class="col-kind">kind</th>
|
||||
<th class="col-kubeconfig">kubeconfig</th>
|
||||
<th class="col-version">Версия</th>
|
||||
<th class="col-workers">Workers</th>
|
||||
<th class="col-state">Состояние</th>
|
||||
<th class="col-actions">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p id="list-msg" class="msg muted"></p>
|
||||
</section>
|
||||
|
||||
{% include "partials/dashboard_modals.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/static/js/dashboard.js" defer></script>
|
||||
{% endblock %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{# Главная: создание (CTA), статистика, донаты, таблица кластеров.
|
||||
{# Главная: CTA, статистика, карточка «Ресурсы узлов» (только донаты); список кластеров на /clusters.
|
||||
Автор: Сергей Антропов — https://devops.org.ru #}
|
||||
{% extends "base.html" %}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<div class="cta-hero-inner">
|
||||
<h1 class="page-title" id="cta-hero-title">Создать кластер</h1>
|
||||
<p class="muted page-lead cta-hero-lead">
|
||||
Кластеры kind, kubeconfig и kubectl — ниже на странице. Данные обновляются автоматически.
|
||||
Список кластеров, сводка по узлам и действия — на странице <a href="/clusters">Кластеры</a>. Данные там обновляются автоматически.
|
||||
</p>
|
||||
<a href="/cluster-create" class="btn btn-cta-large">Перейти к форме создания</a>
|
||||
</div>
|
||||
@@ -53,30 +53,15 @@
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<section id="aggregate-donuts-section" class="card aggregate-donuts-card" aria-labelledby="donuts-heading">
|
||||
<h2 id="donuts-heading" class="donuts-card-title">Ресурсы узлов (сводка)</h2>
|
||||
<div id="aggregate-donuts" class="aggregate-donuts" aria-live="polite"></div>
|
||||
</section>
|
||||
|
||||
<section class="card clusters-card">
|
||||
<h2>Кластеры</h2>
|
||||
<div class="table-wrap">
|
||||
<table id="tbl-clusters" aria-label="Список кластеров">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-cluster-name">Имя</th>
|
||||
<th class="col-kind">kind</th>
|
||||
<th class="col-kubeconfig">kubeconfig</th>
|
||||
<th class="col-version">Версия</th>
|
||||
<th class="col-workers">Workers</th>
|
||||
<th class="col-state">Состояние</th>
|
||||
<th class="col-actions">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
<section
|
||||
id="home-resources-summary-card"
|
||||
class="card aggregate-donuts-card home-resources-summary-card"
|
||||
aria-labelledby="home-resources-summary-heading"
|
||||
>
|
||||
<div id="home-resources-summary-wrap" class="home-resources-summary-inner">
|
||||
<h2 id="home-resources-summary-heading" class="donuts-card-title">Ресурсы узлов (сводка)</h2>
|
||||
<div id="aggregate-donuts" class="aggregate-donuts" aria-live="polite"></div>
|
||||
</div>
|
||||
<p id="list-msg" class="msg muted"></p>
|
||||
</section>
|
||||
|
||||
{% include "partials/dashboard_modals.html" %}
|
||||
|
||||
+79
-15
@@ -1,4 +1,5 @@
|
||||
{# Агрегированный журнал завершённых заданий (JSON в каталогах кластеров).
|
||||
{# Журналы: задания по кластеру, развёртывание (provision_log), Helm (helm_addon_log).
|
||||
Переключатель режима — как «Простой / Расширенный» на странице редактирования кластера.
|
||||
Автор: Сергей Антропов — https://devops.org.ru #}
|
||||
{% extends "base.html" %}
|
||||
|
||||
@@ -18,7 +19,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{# Полноэкранный спиннер до первой загрузки журнала; скрывается в journal.js #}
|
||||
<div
|
||||
id="journal-page-loading-overlay"
|
||||
class="page-loading-overlay"
|
||||
@@ -35,36 +35,100 @@
|
||||
</div>
|
||||
|
||||
<section class="card hero-panel cluster-create-hero" aria-labelledby="journal-hero-title">
|
||||
<h1 class="page-title" id="journal-hero-title">Журнал заданий</h1>
|
||||
<p class="muted page-lead">
|
||||
Записи о завершённых операциях (<strong>create</strong>, <strong>start</strong>, <strong>stop</strong> и др.) хранятся в
|
||||
<code>clusters/<имя>/journal/jobs_history.json</code> на томе с хоста. Сводка по всем кластерам, по <strong>30</strong> записей на страницу;
|
||||
детали задания в процессе — по-прежнему в <a href="/cluster-create">создании кластера</a> и <code>GET /api/v1/jobs/{id}</code>.
|
||||
</p>
|
||||
<h1 class="page-title" id="journal-hero-title">Журналы</h1>
|
||||
</section>
|
||||
|
||||
<section class="card create-cluster-card journal-toolbar-card">
|
||||
<h2 class="create-cluster-card__title">Действия</h2>
|
||||
<div class="journal-toolbar-row">
|
||||
<h2 class="create-cluster-card__title">Вид журнала</h2>
|
||||
|
||||
<fieldset class="cluster-edit-mode-fieldset journal-view-fieldset">
|
||||
<legend class="cluster-edit-mode-legend">Режим просмотра</legend>
|
||||
<div
|
||||
class="cluster-edit-segmented"
|
||||
role="radiogroup"
|
||||
aria-label="Какой журнал показывать"
|
||||
>
|
||||
<div class="cluster-edit-segment-item">
|
||||
<input
|
||||
type="radio"
|
||||
name="journal_view"
|
||||
id="journal-seg-per-cluster"
|
||||
class="cluster-edit-segment-native"
|
||||
value="per_cluster"
|
||||
checked
|
||||
/>
|
||||
<label for="journal-seg-per-cluster" class="cluster-edit-segment-label">
|
||||
<span class="cluster-edit-segment-title">По кластеру</span>
|
||||
<span class="cluster-edit-segment-sub-wrap">
|
||||
<span class="cluster-edit-segment-sub">История заданий</span>
|
||||
<span class="cluster-edit-segment-sub">create / start / stop</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="cluster-edit-segment-item">
|
||||
<input
|
||||
type="radio"
|
||||
name="journal_view"
|
||||
id="journal-seg-provision"
|
||||
class="cluster-edit-segment-native"
|
||||
value="provision"
|
||||
/>
|
||||
<label for="journal-seg-provision" class="cluster-edit-segment-label">
|
||||
<span class="cluster-edit-segment-title">Развёртывание</span>
|
||||
<span class="cluster-edit-segment-sub-wrap">
|
||||
<span class="cluster-edit-segment-sub">Последний provision_log</span>
|
||||
<span class="cluster-edit-segment-sub">по каждому кластеру</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="cluster-edit-segment-item">
|
||||
<input
|
||||
type="radio"
|
||||
name="journal_view"
|
||||
id="journal-seg-helm"
|
||||
class="cluster-edit-segment-native"
|
||||
value="helm_addons"
|
||||
/>
|
||||
<label for="journal-seg-helm" class="cluster-edit-segment-label">
|
||||
<span class="cluster-edit-segment-title">Helm-аддоны</span>
|
||||
<span class="cluster-edit-segment-sub-wrap">
|
||||
<span class="cluster-edit-segment-sub">История операций Helm</span>
|
||||
<span class="cluster-edit-segment-sub">install / delete</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div id="journal-cluster-picker" class="journal-cluster-picker">
|
||||
<label for="journal-cluster-select" class="journal-cluster-picker-label">Кластер</label>
|
||||
<select id="journal-cluster-select" class="journal-cluster-select" aria-describedby="journal-cluster-picker-hint">
|
||||
<option value="">— загрузка —</option>
|
||||
</select>
|
||||
<p id="journal-cluster-picker-hint" class="muted journal-cluster-picker-hint">
|
||||
Журнал заданий только для выбранного каталога в <code>clusters/</code>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="journal-toolbar-actions">
|
||||
<button type="button" class="btn-secondary" id="journal-refresh-btn">Обновить</button>
|
||||
<span class="muted journal-page-size-hint">На странице по <strong>30</strong> записей.</span>
|
||||
</div>
|
||||
<p id="journal-status" class="muted journal-status" role="status" aria-live="polite"></p>
|
||||
</section>
|
||||
|
||||
<section class="card journal-list-card">
|
||||
<h2 class="create-cluster-card__title">Последние записи</h2>
|
||||
<div id="journal-empty" class="muted journal-empty hidden">Нет записей в журналах кластеров (или каталоги кластеров ещё не созданы).</div>
|
||||
<h2 class="create-cluster-card__title" id="journal-table-section-title">Записи</h2>
|
||||
<div id="journal-empty" class="muted journal-empty hidden">Нет записей.</div>
|
||||
<div id="journal-table-wrap" class="journal-table-wrap">
|
||||
<table class="journal-table" id="journal-table" aria-describedby="journal-hero-title">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Завершено (UTC)</th>
|
||||
<th scope="col">Кластер</th>
|
||||
<th scope="col">Тип</th>
|
||||
<th scope="col" id="journal-th-kind">Тип / операция</th>
|
||||
<th scope="col">Статус</th>
|
||||
<th scope="col">Сообщение</th>
|
||||
<th scope="col">Журнал</th>
|
||||
<th scope="col">Лог</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="journal-tbody"></tbody>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Журнал фонового задания (ошибка / отмена) — страница «Последние задания». #}
|
||||
{# Журнал задания по API GET /jobs/{id} (модалка при необходимости из скриптов). #}
|
||||
<div
|
||||
id="job-log-modal-overlay"
|
||||
class="modal-overlay job-log-modal-overlay hidden"
|
||||
|
||||
Reference in New Issue
Block a user