first commit

This commit is contained in:
Sergey Antropoff
2026-04-04 05:15:54 +03:00
commit ae961ef5fe
25 changed files with 2022 additions and 0 deletions
+148
View File
@@ -0,0 +1,148 @@
#!/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 _run(cmd: list[str]) -> int:
p = subprocess.run(cmd, capture_output=True, text=True)
if p.stdout:
print(p.stdout, end="")
if p.stderr:
print(p.stderr, end="", file=sys.stderr)
return p.returncode
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 delete (или make delete из каталога репозитория).", 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()