Панель: редактирование конфига кластера, reapply при старте, UI и таблица
- PUT/GET конфигурации кластера, страница редактирования и модалка после сохранения - После смены kind-config: флаг в meta и start_cluster_reapply (kind delete + create) - Старт/стоп: полноэкранный спиннер до завершения job; модалки и документация API - Таблица кластеров: колонка Имя 40% при table-layout fixed; чекбоксы без width 100% - Карточки ресурсов узлов на странице кластера: до 3 в ряд; прочие правки стилей и dashboard.js
This commit is contained in:
@@ -630,6 +630,11 @@ def create_cluster_non_interactive(
|
||||
}
|
||||
if patched:
|
||||
meta["kubeconfig_host_path"] = str(host_kube_path.relative_to(root))
|
||||
# Сохраняем описание из прежнего meta.json при подъёме по существующему конфигу (в т.ч. reapply).
|
||||
if use_existing_config:
|
||||
desc = prev_meta_for_workers.get("description")
|
||||
if isinstance(desc, str) and desc.strip():
|
||||
meta["description"] = desc.strip()[:2000]
|
||||
meta_path.write_text(json.dumps(meta, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
_progress("Завершение", 95)
|
||||
@@ -694,6 +699,55 @@ def delete_kind_cluster_and_data(*, name: str, log_to_stdout: bool = False) -> t
|
||||
return kind_ok, "; ".join(parts)
|
||||
|
||||
|
||||
def delete_kind_cluster_keep_data(*, name: str, job_id: str | None = None) -> tuple[bool, str]:
|
||||
"""
|
||||
Выполнить ``kind delete cluster`` без удаления каталога ``clusters/<имя>/``.
|
||||
|
||||
Используется после изменения ``kind-config.yaml``: затем ``kind create`` поднимает узлы
|
||||
по новому файлу. Если запись в kind уже отсутствует — считаем шаг успешным и идём к create.
|
||||
|
||||
При ``job_id`` вывод и отмена — как у других длительных операций (см. ``_run_checked_stream``).
|
||||
|
||||
Автор: Сергей Антропов
|
||||
Сайт: https://devops.org.ru
|
||||
"""
|
||||
from core import job_store as _js
|
||||
|
||||
def _log(line: str) -> None:
|
||||
if job_id:
|
||||
_js.append_log_sync(job_id, line)
|
||||
|
||||
if not shutil.which("kind"):
|
||||
raise KindClusterError("Не найден kind в PATH.", exit_code=127)
|
||||
|
||||
if job_id and _js.is_cancelled_sync(job_id):
|
||||
raise KindClusterError("Операция отменена", exit_code=130)
|
||||
|
||||
_log("Удаление записи кластера в kind (каталог clusters/<имя>/ на диске не удаляется).")
|
||||
logger.info("kind delete с сохранением каталога данных для «%s»", name)
|
||||
|
||||
try:
|
||||
_run_checked_stream(
|
||||
["kind", "delete", "cluster", "--name", name],
|
||||
on_line=_log if job_id else None,
|
||||
job_id=job_id,
|
||||
)
|
||||
return True, "kind delete: OK"
|
||||
except KindClusterError as e:
|
||||
if job_id and _js.is_cancelled_sync(job_id):
|
||||
raise KindClusterError("Операция отменена", exit_code=130) from e
|
||||
# kind иногда возвращает ошибку, если кластер уже снят с учёта — проверяем фактическое состояние
|
||||
remaining = list_registered_kind_clusters()
|
||||
if name not in remaining:
|
||||
_log("Запись кластера в kind отсутствует — далее создание по сохранённому kind-config.yaml.")
|
||||
logger.info(
|
||||
"После сбоя kind delete кластер «%s» не в списке зарегистрированных — продолжаем",
|
||||
name,
|
||||
)
|
||||
return True, "Запись в kind уже отсутствовала"
|
||||
raise
|
||||
|
||||
|
||||
def _sort_kind_node_containers(names: list[str]) -> list[str]:
|
||||
"""Сначала control-plane, затем остальные — удобнее для ``docker start``."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user