Документация и kubectl из контейнера; Kind Clusters Dashboard

- Цель make docker|podman kubectl CLUSTER=… (KUBECTL_ARGS) — exec kubectl в kind-k8s-web
- README: без kubectl на хосте; раздел про проверку API из контейнера
- create_cluster/cluster_status: подсказки для UI, make kubectl и exec в контейнере
- app/docs: api_routes.md и README.md про kubectl и API workloads
- Прочее: переименование проекта, документация, UI документации (ранее в рабочем дереве)
This commit is contained in:
Sergey Antropoff
2026-04-04 06:27:18 +03:00
parent c1e867a01f
commit d1a01cca9e
17 changed files with 483 additions and 131 deletions
+40 -3
View File
@@ -1,4 +1,4 @@
"""Отдача сырого README.md для клиентского рендера Markdown (marked в static).
"""Отдача README.md и файлов ``app/docs/*.md`` для клиентского рендера Markdown (marked в static).
Автор: Сергей Антропов
Сайт: https://devops.org.ru
@@ -9,10 +9,10 @@ from __future__ import annotations
import asyncio
import logging
from fastapi import APIRouter, HTTPException
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import PlainTextResponse
from core.readme_doc import read_readme_text
from core.readme_doc import read_app_docs_file_text, read_readme_text
logger = logging.getLogger("kind_k8s.api.docs_readme")
@@ -51,3 +51,40 @@ async def get_readme_markdown() -> PlainTextResponse:
content=text,
media_type="text/markdown; charset=utf-8",
)
@router.get(
"/docs/file",
response_class=PlainTextResponse,
summary="Файл Markdown под app/docs/",
responses={400: {"description": "Некорректный путь"}, 403: {"description": "Вне app/docs"}, 404: {"description": "Нет файла"}},
)
async def get_app_docs_file(
path: str = Query(
...,
description="Относительный путь, например app/docs/api_routes.md",
examples=["app/docs/api_routes.md"],
),
) -> PlainTextResponse:
"""
Только файлы ``*.md`` с префиксом ``app/docs/`` (без ``..``).
Ссылки из README ведут на ``/documentation?path=...``; клиент запрашивает этот эндпоинт.
"""
try:
def _read() -> str:
return read_app_docs_file_text(path)
text = await asyncio.to_thread(_read)
except FileNotFoundError:
logger.info("GET /docs/file: не найден или запрещён путь %s", path)
raise HTTPException(
status_code=404,
detail="Файл не найден или путь не разрешён (ожидается app/docs/<имя>.md).",
) from None
logger.debug("GET /docs/file: отдан %s", path)
return PlainTextResponse(
content=text,
media_type="text/markdown; charset=utf-8",
)