Веб-UI FastAPI, REST API v1, интерактивный setup без env.example
- Дашборд (Jinja2 + static), управление кластерами kind, задания и kubeconfig. - API: health, stats, clusters CRUD, versions, jobs; документация app/docs/api_routes.md. - Docker Compose: том app, uvicorn reload, KIND_K8S_PATCH_KUBECONFIG по умолчанию 1. - setup_env_interactive.py: список переменных в скрипте, удалён env.example. - Makefile: явный префикс docker/podman; прочие правки CLI и ядра кластеров.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
{# Общий каркас страниц веб-интерфейса kind-k8s-develop.
|
||||
Автор: Сергей Антропов — https://devops.org.ru #}
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{% block page_title %}{{ app_title }}{% endblock %} — kind</title>
|
||||
<link rel="stylesheet" href="/static/style.css" />
|
||||
{% block head_extra %}{% endblock %}
|
||||
</head>
|
||||
<body
|
||||
class="app-body"
|
||||
data-api-base="/api/v1"
|
||||
data-app-title="{{ app_title | e }}"
|
||||
>
|
||||
<a class="skip-link" href="#main-content">К основному содержимому</a>
|
||||
|
||||
<header class="top-nav" role="banner">
|
||||
<div class="top-nav-inner">
|
||||
<div class="nav-brand">
|
||||
<span class="nav-logo" aria-hidden="true">◈</span>
|
||||
<span class="nav-title">{{ app_title }}</span>
|
||||
<span class="nav-tag muted">kind · локальные кластеры</span>
|
||||
</div>
|
||||
<nav class="nav-links" aria-label="Разделы">
|
||||
<a href="/" class="nav-link">Панель</a>
|
||||
<a href="/docs" class="nav-link" target="_blank" rel="noopener">Swagger</a>
|
||||
<a href="/redoc" class="nav-link" target="_blank" rel="noopener">ReDoc</a>
|
||||
<a href="/api/v1/health" class="nav-link" target="_blank" rel="noopener">Health</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div id="toast" class="toast hidden" role="status" aria-live="polite"></div>
|
||||
|
||||
<main id="main-content" class="app-main" tabindex="-1">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<footer class="footer muted app-footer">
|
||||
{% block footer %}
|
||||
<span>Данные: том <code>clusters/</code> на хосте · <code>app/docs/api_routes.md</code></span>
|
||||
{% endblock %}
|
||||
</footer>
|
||||
|
||||
{% block scripts %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,158 @@
|
||||
{# Главная панель: кластеры, задания, создание.
|
||||
Расширяет base.html; логика в /static/js/dashboard.js.
|
||||
Автор: Сергей Антропов — https://devops.org.ru #}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block footer %}
|
||||
<span>Документация API: <code>app/docs/api_routes.md</code> · том данных <code>clusters/</code></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="page-intro">
|
||||
<h1 class="page-title">Панель управления</h1>
|
||||
<p class="muted page-lead">
|
||||
Создание и удаление кластеров kind, kubeconfig и просмотр узлов/подов через kubectl внутри контейнера.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="status-banner" class="status-banner muted" role="status" aria-live="polite">
|
||||
Проверка среды…
|
||||
</div>
|
||||
|
||||
<div class="toolbar row spread">
|
||||
<div class="row" style="margin-top:0;align-items:center;gap:0.75rem">
|
||||
<button type="button" id="btn-refresh-all" class="btn-secondary">Обновить всё</button>
|
||||
<label class="row" style="margin-top:0;align-items:center;gap:0.35rem">
|
||||
<input type="checkbox" id="auto-refresh" />
|
||||
авто каждые 15 с
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="grid">
|
||||
<div class="card">
|
||||
<h2>Статистика</h2>
|
||||
<dl id="stats-dl" class="stats-dl" aria-label="Сводка по кластерам и заданиям"></dl>
|
||||
<p id="stats-err" class="msg hidden" role="alert"></p>
|
||||
<div class="row">
|
||||
<button type="button" id="btn-refresh-stats">Обновить статистику</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Создать кластер</h2>
|
||||
<form id="form-create" novalidate>
|
||||
<label for="fld-name">Имя (a-z0-9-)</label>
|
||||
<input
|
||||
id="fld-name"
|
||||
name="name"
|
||||
required
|
||||
pattern="[a-z0-9]([-a-z0-9]*[a-z0-9])?"
|
||||
maxlength="63"
|
||||
placeholder="dev"
|
||||
autocomplete="off"
|
||||
/>
|
||||
|
||||
<label for="version-select">Тег образа kindest/node (подсказка)</label>
|
||||
<div class="row">
|
||||
<select id="version-select" name="kubernetes_version_preset" aria-describedby="ver-hint">
|
||||
<option value="">— загрузить список —</option>
|
||||
</select>
|
||||
</div>
|
||||
<p id="ver-hint" class="muted" style="margin:0.25rem 0 0;font-size:0.85rem">
|
||||
Можно ввести версию вручную ниже.
|
||||
</p>
|
||||
<label for="kubernetes_version">Версия Kubernetes / тег node</label>
|
||||
<input
|
||||
name="kubernetes_version"
|
||||
id="kubernetes_version"
|
||||
required
|
||||
placeholder="1.29.4 или v1.29.4"
|
||||
autocomplete="off"
|
||||
/>
|
||||
|
||||
<label for="fld-workers">Worker-ноды (0–20)</label>
|
||||
<input id="fld-workers" name="workers" type="number" min="0" max="20" value="2" />
|
||||
|
||||
<button type="submit">Создать кластер</button>
|
||||
</form>
|
||||
<p id="create-msg" class="msg" aria-live="polite"></p>
|
||||
<details id="job-details" class="job-details hidden">
|
||||
<summary>Ход задания (JSON)</summary>
|
||||
<pre id="job-json" class="mono job-json-pre" tabindex="0"></pre>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card clusters-card">
|
||||
<div class="row spread">
|
||||
<h2>Кластеры</h2>
|
||||
<button type="button" class="btn-secondary" id="btn-refresh-list">Обновить список</button>
|
||||
</div>
|
||||
<div class="table-wrap" data-busy="clusters">
|
||||
<table id="tbl-clusters" aria-label="Список кластеров">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Имя</th>
|
||||
<th>kind</th>
|
||||
<th>kubeconfig</th>
|
||||
<th>Версия</th>
|
||||
<th>Workers</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p id="list-msg" class="msg muted"></p>
|
||||
</section>
|
||||
|
||||
<section class="card jobs-card">
|
||||
<div class="row spread">
|
||||
<h2>Последние задания</h2>
|
||||
<button type="button" class="btn-secondary" id="btn-refresh-jobs">Обновить</button>
|
||||
</div>
|
||||
<div class="table-wrap" data-busy="jobs">
|
||||
<table id="tbl-jobs" aria-label="Последние задания создания">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Время (UTC)</th>
|
||||
<th>Кластер</th>
|
||||
<th>Статус</th>
|
||||
<th>Сообщение</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p id="jobs-msg" class="msg muted"></p>
|
||||
</section>
|
||||
|
||||
<div
|
||||
id="modal-overlay"
|
||||
class="modal-overlay hidden"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="modal-title"
|
||||
>
|
||||
<div class="modal-box">
|
||||
<div class="modal-head row spread">
|
||||
<h3 id="modal-title" class="modal-title-text">Состояние кластера</h3>
|
||||
<button type="button" class="modal-close btn-secondary" id="modal-close">Закрыть</button>
|
||||
</div>
|
||||
<div id="modal-spinner" class="modal-spinner hidden" aria-hidden="true">
|
||||
<span class="spinner" aria-label="Загрузка"></span>
|
||||
<span class="muted">Запрос kubectl…</span>
|
||||
</div>
|
||||
<p id="modal-sub" class="muted modal-sub"></p>
|
||||
<h4 class="modal-section-title muted">Узлы</h4>
|
||||
<pre id="modal-nodes" class="mono" role="region" aria-label="Вывод kubectl get nodes"></pre>
|
||||
<h4 class="modal-section-title muted">Поды (все namespace)</h4>
|
||||
<pre id="modal-pods" class="mono" role="region" aria-label="Вывод kubectl get pods"></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/static/js/dashboard.js" defer></script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user