# Описание REST API веб-интерфейса kind-k8s-develop **Базовый префикс:** `/api/v1` **Автор:** Сергей Антропов — [devops.org.ru](https://devops.org.ru) Интерактивная документация OpenAPI: после запуска `make docker up` откройте [http://127.0.0.1:6000/docs](http://127.0.0.1:6000/docs). --- ## GET /api/v1/health Проверка: `kind`/`kubectl` в PATH и ответ движка контейнеров (`docker info` / `podman info` по `CONTAINER_CLI`). `status`: `ok` — всё готово к созданию кластеров; `degraded` — чего-то не хватает (см. поля ниже). **Пример ответа 200 (JSON):** ```json { "status": "ok", "kind_in_path": true, "kubectl_in_path": true, "container_cli": "docker", "container_engine_ok": true, "container_engine_detail": null } ``` **Если сокет Docker недоступен:** ```json { "status": "degraded", "kind_in_path": true, "kubectl_in_path": true, "container_cli": "docker", "container_engine_ok": false, "container_engine_detail": "Cannot connect to the Docker daemon..." } ``` --- ## GET /api/v1/versions Список стабильных тегов `kindest/node` с Docker Hub (для выпадающего списка в UI). При `KIND_K8S_SKIP_VERSION_LIST=1` список пустой. **Пример ответа 200:** ```json { "tags": ["v1.32.0", "v1.31.4"], "skipped": false } ``` **Пример при пропуске загрузки:** ```json { "tags": [], "skipped": true, "reason": "KIND_K8S_SKIP_VERSION_LIST" } ``` --- ## GET /api/v1/stats Сводная статистика для дашборда. **Пример ответа 200:** ```json { "kind_clusters_count": 2, "local_cluster_dirs_count": 2, "total_workers_from_meta": 4, "jobs_total": 5, "jobs_recent_failed": 1 } ``` Поле `total_workers_from_meta` может быть `null`, если ни в одном `meta.json` нет `worker_nodes`. --- ## GET /api/v1/clusters Список имён: объединение `kind get clusters` и подкаталогов `clusters/*`. **Пример ответа 200 (массив):** ```json [ { "name": "dev", "registered_in_kind": true, "has_local_kubeconfig": true, "meta": { "cluster_name": "dev", "kubernetes_version_tag": "v1.29.4", "node_image": "kindest/node:v1.29.4", "worker_nodes": 2, "kubeconfig_patched_for_host": true } } ] ``` --- ## GET /api/v1/jobs Список последних фоновых заданий (создание кластера), от новых к старым. Данные только в памяти процесса. **Query:** `limit` (1–200, по умолчанию 30). **Пример ответа 200 (массив `JobView`):** ```json [ { "job_id": "abc123", "kind": "create_cluster", "status": "success", "cluster_name": "dev", "created_at_utc": "2026-04-04T12:00:00+00:00", "message": "Кластер создан", "result": { "cluster_name": "dev", "kubernetes_version_tag": "v1.29.4" } } ] ``` --- ## GET /api/v1/clusters/{name}/kubeconfig Скачать файл `kubeconfig` (ответ — тело файла, `Content-Disposition` с именем `kubeconfig-{name}.yaml`). **Ошибка 404:** файла нет в `clusters/{name}/`. --- ## GET /api/v1/clusters/{name}/workloads `kubectl get nodes -o wide` и `kubectl get pods -A` по сохранённому kubeconfig. **Пример ответа 200:** ```json { "cluster_name": "dev", "nodes_rc": 0, "nodes_output": "NAME STATUS ROLES ...", "pods_rc": 0, "pods_output": "NAMESPACE NAME READY STATUS ...", "error": null } ``` Если kubeconfig нет: `"error": "Нет сохранённого kubeconfig..."`, остальные поля подов/узлов — `null`. --- ## GET /api/v1/clusters/{name} Детали и попытка `kubectl get nodes -o wide` с **сохранённого** `clusters/{name}/kubeconfig` (если файл есть). **Пример ответа 200:** ```json { "name": "dev", "registered_in_kind": true, "has_local_kubeconfig": true, "kubeconfig_path": "/work/clusters/dev/kubeconfig", "meta": { "worker_nodes": 2 }, "kubectl_get_nodes_rc": 0, "kubectl_get_nodes": "NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME\n..." } ``` --- ## POST /api/v1/clusters Создание кластера **в фоне** (ответ 202). **Тело запроса (JSON):** ```json { "name": "dev", "kubernetes_version": "1.29.4", "workers": 2 } ``` **Пример ответа 202:** ```json { "job_id": "a1b2c3d4e5f6...", "status": "queued", "message": "Создание кластера выполняется в фоне; опросите GET /api/v1/jobs/{job_id}" } ``` **Ошибка 409 (кластер уже есть в kind):** ```json { "detail": "Кластер с таким именем уже есть в kind" } ``` --- ## GET /api/v1/jobs/{job_id} Статус фонового задания создания. **В процессе (пример 200):** ```json { "job_id": "a1b2...", "kind": "create_cluster", "status": "running", "cluster_name": "dev", "created_at_utc": "2026-04-04T12:00:00+00:00", "message": null, "result": null } ``` **Успех (пример 200):** ```json { "job_id": "a1b2...", "kind": "create_cluster", "status": "success", "cluster_name": "dev", "created_at_utc": "2026-04-04T12:00:00+00:00", "message": "Кластер создан", "result": { "cluster_name": "dev", "kubernetes_version_tag": "v1.29.4", "node_image": "kindest/node:v1.29.4", "workers": 2, "kubeconfig_path": "/work/clusters/dev/kubeconfig", "kubeconfig_patched_for_host": true, "nodes_ready": true, "nodes_ready_message": "..." } } ``` **Ошибка 404:** ```json { "detail": "Задание не найдено" } ``` --- ## DELETE /api/v1/clusters/{name} `kind delete cluster` и удаление каталога `clusters/{name}/`. **Пример ответа 200:** ```json { "name": "dev", "kind_delete_ok": true, "summary": "kind delete: OK; удалена папка /work/clusters/dev" } ``` --- ## GET / HTML-дашборд (не JSON): форма создания, таблица кластеров, ссылки на Swagger.