Files
KindClustersDashboard/app/delete_cluster.py
Sergey Antropoff d1a01cca9e Документация и 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 документации (ранее в рабочем дереве)
2026-04-04 06:27:18 +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 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()