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:
Sergey Antropoff
2026-04-04 18:54:10 +03:00
parent 349b78d24d
commit 4b703801e1
13 changed files with 415 additions and 123 deletions
+19 -6
View File
@@ -52,6 +52,7 @@
| GET | `/api/v1/clusters/{name}/config` | Текущие `meta.json` и текст `kind-config.yaml`; подсказка `kind_note` про пересоздание |
| PUT | `/api/v1/clusters/{name}/config` | Сохранить YAML и/или meta (простой режим или полный YAML); ответ включает обновлённый `summary` |
| GET | `/api/v1/clusters/{name}/kubeconfig` | Скачать файл kubeconfig |
| GET | `/api/v1/clusters/{name}/kubeconfig/docker` | Скачать kubeconfig для kubectl из **любого** контейнера: `host.docker.internal:<порт>` + `tls-server-name` (запасной вариант — `*-control-plane:6443`) |
| GET | `/api/v1/clusters/{name}/provision-log` | Полный журнал последнего **create_cluster** / **start_cluster** / **start_cluster_reapply** (JSON с диска) |
| GET | `/api/v1/clusters/{name}/workloads` | Узлы и поды (`kubectl`) |
| GET | `/api/v1/clusters/{name}/overview` | Сводка для страницы UI: метрики узлов, агрегаты, блоки **`k8s_*`** (JSON из `kubectl get … -o json`) |
@@ -79,7 +80,7 @@
| DELETE | `/api/v1/jobs` | Удалить из памяти **завершённые** задания (`removed` — число записей) |
| POST | `/api/v1/jobs/{job_id}/cancel` | Прервать задание: активная команда завершается принудительно (скачивание образа, создание кластера, старт/стоп узла) |
После каждого **POST/DELETE …/addons/…** в каталоге кластера в **`helm_addon_log.json`** **добавляется** новая запись в массив **`entries`** (история сохраняется, лимит **`KIND_K8S_HELM_ADDON_LOG_MAX_ENTRIES`**). Формат записи как у **`provision_log.json`**: `lines`, `kind`, `status`, `result`; пароли в файл не пишутся.
После каждого **POST/DELETE …/addons/…** в каталоге кластера в **`helm_addon_log.json`** **добавляется** новая запись в массив **`entries`** (история сохраняется, лимит **`KIND_K8S_HELM_ADDON_LOG_MAX_ENTRIES`**). Формат записи как у **`provision_log.json`**: `lines`, `kind`, `status`, **`message`** (краткая подпись на русском при успехе), **`result`**; в **`result`** поля **`addon`** и **`action`**: **`install`** | **`upgrade`** (повторный POST при уже установленном релизе) | **`delete`**; пароли в файл не пишутся. Поле **`kind`**: `helm_addon_install_*`, `helm_addon_upgrade_*`, `helm_addon_delete_*` (суффикс — аддон в snake_case).
#### POST `/api/v1/helm/addons/compose-values-batch`
@@ -105,7 +106,7 @@
- **ingress-nginx** — один файл **`-f`** с полным values; затем **`--set`** NodePort (сильнее файла).
- **kube-prometheus-stack** — один файл: либо из **`values_yaml`**, либо автосборка из версии и полей Grafana.
- **metrics-server** — аналогично.
- **istio-kiali** — до трёх опциональных файлов: **istio/base**, **istio/istiod**, **kiali-server**; секрет логина Kiali и **`auth.strategy=login`** отдельно.
- **istio-kiali** — до трёх опциональных файлов: **istio/base**, **istio/istiod**, **kiali-server**. Если в YAML kiali-server **нет** `auth.strategy`, сервер задаёт **`auth.strategy=anonymous`** (стратегия **login** в актуальных версиях Kiali не поддерживается). Логин/пароль Kiali в теле запроса **не** передаются.
**Пример POST compose-values (`kube-prometheus-stack`):**
@@ -120,12 +121,10 @@
**Пример ответа 200 (фрагмент):** поле **`values_yaml`** — многострочная строка с полным YAML чарта.
**Пример POST установки istio-kiali с тремя YAML:**
**Пример POST установки istio-kiali с тремя YAML** (Kiali с **token**, если задано в `values_yaml`; иначе будет **anonymous**):
```json
{
"kiali_username": "kiali-admin",
"kiali_password": "MySecurePwd12",
"istio_chart_version": "1.22.0",
"kiali_chart_version": "1.89.0",
"istio_base_values_yaml": "defaultRevision: default\n",
@@ -140,7 +139,7 @@
- В памяти держится не более **200** записей; при превышении старые задания вытесняются (`app/core/job_store.py`).
- Снимок заданий сохраняется в JSON в каталоге **`clusters/`** (файл **`kind_k8s_jobs.json`** на томе с хоста) — после перезапуска контейнера список восстанавливается. Записи в статусе **queued**/**running** при старте помечаются как **failed** (процесс уже не выполняется). Путь переопределяется переменной **`KIND_K8S_JOBS_JSON`**.
- При **завершении** задания (успех / ошибка / отмена), если указано **`cluster_name`** и существует каталог **`clusters/<имя>/`**, в **`clusters/<имя>/journal/jobs_history.json`** дозаписывается запись с хвостом лога и **`result`** (без секретов). Лимиты: **`KIND_K8S_CLUSTER_JOURNAL_MAX_ENTRIES`**, **`KIND_K8S_CLUSTER_JOURNAL_MAX_LOG_LINES`**. Чтение: **`GET /api/v1/journal/recent?cluster=…`**, **`GET /api/v1/clusters/{name}/journal`**, страница **`GET /journal`** (режим «По кластеру»).
- Операции **Helm-аддонов** (install/delete) **дописывают** запись в **`clusters/<имя>/helm_addon_log.json`** (массив **`entries`**, новые сверху), тот же набор полей, что у **`provision_log.json`**. Сводка по всем кластерам: **`GET /api/v1/journal/helm-addons`**.
- Операции **Helm-аддонов** (первая установка, **обновление** через тот же POST при уже установленном релизе, удаление) **дописывают** запись в **`clusters/<имя>/helm_addon_log.json`** (массив **`entries`**, новые сверху). Сводка по всем кластерам: **`GET /api/v1/journal/helm-addons`**; на странице **`/journal`** режим **Helm-аддоны** показывает тип операции и аддон в человекочитаемом виде.
- Создание кластера: `POST /api/v1/clusters` → опрос `GET /api/v1/jobs/{job_id}` (как в веб-UI).
- В ответе задания поля **`progress_stage`** (текст этапа) и **`progress_percent`** (0–100) обновляются во время создания.
- В **GET /api/v1/jobs** (список) поле **`progress_log`** всегда **пустой массив** — меньше трафика; полный хвост — в **GET /api/v1/jobs/{job_id}** (лимит строк: `KIND_K8S_JOB_API_LOG_MAX_LINES`, по умолчанию **5000**).
@@ -623,6 +622,20 @@ Accept: text/markdown
---
## GET /api/v1/clusters/{name}/kubeconfig/docker
Скачать kubeconfig для **kubectl из произвольного контейнера** (`Content-Disposition`: `kubeconfig-docker-{name}.yaml`).
Логика как у **kubectl внутри веб-контейнера** (`kubeconfig_patch.apply_apiserver_endpoint_to_kubeconfig_file`): при успешном **`docker port <имя>-control-plane 6443/tcp`** — **`server=https://<KIND_K8S_APISERVER_GATEWAY_HOST>:<порт>`** (по умолчанию **host.docker.internal**) и **`tls-server-name`** из **`KIND_K8S_KUBECONFIG_TLS_SERVER_NAME`** (по умолчанию **localhost**). Иначе запасной **`server=https://<имя>-control-plane:6443`** без SNI. На Linux у клиентского контейнера обычно нужен **`extra_hosts: host.docker.internal:host-gateway`**.
**Ошибка 404:** нет файла **`kubeconfig`** в `clusters/{name}/`.
**Ошибка 500:** не удалось выполнить `kubectl config set-cluster` / задать SNI.
**Ошибка 400:** некорректное имя кластера.
---
## GET /api/v1/clusters/{name}/provision-log
Содержимое **`clusters/<имя>/provision_log.json`**: полный журнал строк последнего завершённого задания **create_cluster**, **start_cluster** или **start_cluster_reapply** (включая успех, ошибку и отмену), плюс метаданные (`job_id`, `kind`, `status`, `message`, `result`, `finished_at_utc`).