Files
KindClustersDashboard/app/delete_cluster.py
T
Sergey Antropoff e46a62cfdb Веб-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 и ядра кластеров.
2026-04-04 05:39:53 +03:00

140 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Интерактивное или пакетное удаление кластера kind и локальной папки с конфигами.
Автор: Сергей Антропов
Сайт: https://devops.org.ru
Пакетный режим: ``--non-interactive --name ИМЯ [--yes]`` (``--yes`` пропускает подтверждение).
"""
from __future__ import annotations
import argparse
import logging
import shutil
import subprocess
import sys
from core.cluster_lifecycle import KindClusterError, delete_kind_cluster_and_data
from kind_k8s_paths import clusters_dir
def _configure_logging() -> None:
if logging.root.handlers:
return
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s: %(message)s")
def _list_kind_clusters() -> list[str]:
p = subprocess.run(["kind", "get", "clusters"], capture_output=True, text=True)
if p.returncode != 0:
return []
lines = [x.strip() for x in (p.stdout or "").splitlines() if x.strip()]
return [x for x in lines if x.lower() not in ("no kind clusters found.", "no kind clusters found")]
def _ask(prompt: str) -> str:
return input(f"{prompt}: ").strip()
def _interactive() -> None:
print("=== Удаление кластера kind ===\n")
CLUSTERS_DIR = clusters_dir()
if not shutil.which("kind"):
print("Не найден kind.", file=sys.stderr)
print(" Через Docker: make -C kind-k8s-develop docker up и удаление в веб-интерфейсе.", file=sys.stderr)
sys.exit(127)
clusters = _list_kind_clusters()
if not clusters:
print("Нет зарегистрированных кластеров kind.")
only_dirs = (
sorted(p.name for p in CLUSTERS_DIR.iterdir() if p.is_dir() and not p.name.startswith("."))
if CLUSTERS_DIR.is_dir()
else []
)
if only_dirs:
print("Есть локальные папки в clusters/: ", ", ".join(only_dirs))
name = _ask("Удалить только данные в clusters/<имя> (без kind delete)? Введите имя или пусто для выхода")
if not name:
return
d = CLUSTERS_DIR / name
if d.is_dir():
shutil.rmtree(d)
print(f"Удалена папка {d}")
else:
print("Папка не найдена.")
return
print("Существующие кластеры kind:")
for i, c in enumerate(clusters, 1):
print(f" {i}) {c}")
raw = _ask("\nВведите имя кластера или номер из списка")
if not raw:
print("Отмена.")
return
if raw.isdigit():
idx = int(raw, 10)
if idx < 1 or idx > len(clusters):
print("Неверный номер.")
sys.exit(1)
name = clusters[idx - 1]
else:
name = raw
if name not in clusters:
print(f"Кластер «{name}» не найден в kind. Отмена.")
sys.exit(1)
confirm = _ask(f"Удалить кластер «{name}» и папку clusters/{name}? (yes/no)")
if confirm.lower() not in ("yes", "y", "да", "д"):
print("Отмена.")
return
try:
kind_ok, summary = delete_kind_cluster_and_data(name=name, log_to_stdout=True)
except KindClusterError as e:
print(str(e), file=sys.stderr)
raise SystemExit(getattr(e, "exit_code", 1)) from e
if not kind_ok:
print("kind delete завершился с ошибкой; локальная папка удалена при наличии.", file=sys.stderr)
print(summary)
print("Готово.")
def _parse_args() -> argparse.Namespace:
p = argparse.ArgumentParser(description="Удаление кластера kind")
p.add_argument("--non-interactive", action="store_true", help="Без диалогов")
p.add_argument("--name", help="Имя кластера")
p.add_argument("--yes", "-y", action="store_true", help="Не спрашивать подтверждение (только с --non-interactive)")
return p.parse_args()
def main() -> None:
_configure_logging()
args = _parse_args()
if args.non_interactive:
if not args.name:
print("Нужен --name в режиме --non-interactive.", file=sys.stderr)
raise SystemExit(2)
if not args.yes:
print("Добавьте --yes для подтверждения удаления в пакетном режиме.", file=sys.stderr)
raise SystemExit(2)
if not shutil.which("kind"):
print("Не найден kind.", file=sys.stderr)
sys.exit(127)
try:
kind_ok, summary = delete_kind_cluster_and_data(name=args.name.strip())
except KindClusterError as e:
print(str(e), file=sys.stderr)
raise SystemExit(getattr(e, "exit_code", 1)) from e
print(summary)
raise SystemExit(0 if kind_ok else 1)
_interactive()
if __name__ == "__main__":
main()