from __future__ import annotations from pathlib import Path from ._services_common import ( _LogFn, _detect_mode, _docker, _ensure_namespace, _exists, _k3d, _kubectl, _log, _manifest_path, _registry_namespace, _to_bool, _wait_rollout, ) def _ensure_k3d_registry(*, env: dict | None = None, log: _LogFn | None = None) -> None: name = str((env or {}).get("K3D_REGISTRY_NAME") or "prole-registry") port = str((env or {}).get("REGISTRY_PORT") or "5000") listed = _k3d(["registry", "list"], env=env, timeout=60) if listed.returncode == 0 and name in listed.stdout: _log(log, f"[REGISTRY] k3d registry {name} already exists") return _log(log, f"[REGISTRY] Creating k3d registry {name} on port {port}") created = _k3d(["registry", "create", name, "--port", f"{port}:{port}"], env=env, timeout=180) if created.returncode == 0: return # fallback docker registry _log(log, "[REGISTRY] k3d registry creation failed; trying docker registry fallback") running = _docker(["ps", "--format", "{{.Names}}"], env=env, timeout=30) if running.returncode == 0 and name in running.stdout.splitlines(): return _docker(["rm", "-f", name], env=env, timeout=30) _docker( [ "run", "-d", "--restart=always", "-p", f"{port}:5000", "--name", name, "registry:2", ], env=env, timeout=120, check=True, ) def _manifest(project_root: str | Path) -> Path: return _manifest_path(project_root, "k8s", "registry", "deployment.yaml") def initialize( *, namespace: str | None = None, env: dict | None = None, project_root: str | Path = ".", log: _LogFn | None = None, mode: str | None = None, ) -> None: update(namespace=namespace, env=env, project_root=project_root, log=log, mode=mode) def start( *, namespace: str | None = None, env: dict | None = None, project_root: str | Path = ".", log: _LogFn | None = None, mode: str | None = None, ) -> None: update(namespace=namespace, env=env, project_root=project_root, log=log, mode=mode) def update( *, namespace: str | None = None, env: dict | None = None, project_root: str | Path = ".", log: _LogFn | None = None, mode: str | None = None, ) -> None: effective_mode = _detect_mode(mode, env) if effective_mode == "k3d": _ensure_k3d_registry(env=env, log=log) return target_ns = _registry_namespace(namespace, env) _ensure_namespace(target_ns, env) manifest = _manifest(project_root) if not manifest.exists(): raise RuntimeError(f"Registry manifest not found: {manifest}") _log(log, f"[REGISTRY] Applying {manifest}") _kubectl( ["-n", target_ns, "apply", "-f", str(manifest)], env=env, timeout=180, check=True, ) _wait_rollout("deployment", "registry", target_ns, env=env) def stop( *, namespace: str | None = None, env: dict | None = None, mode: str | None = None, log: _LogFn | None = None, ) -> None: effective_mode = _detect_mode(mode, env) if effective_mode == "k3d": name = str((env or {}).get("K3D_REGISTRY_NAME") or "prole-registry") _log(log, f"[REGISTRY] Removing k3d registry {name}") _k3d(["registry", "delete", name], env=env, timeout=120) _docker(["rm", "-f", name], env=env, timeout=30) return target_ns = _registry_namespace(namespace, env) if _exists("deployment", "registry", target_ns, env=env): _kubectl( ["-n", target_ns, "scale", "deployment/registry", "--replicas=0"], env=env, timeout=90, check=True, ) def restart( *, namespace: str | None = None, env: dict | None = None, mode: str | None = None, log: _LogFn | None = None, ) -> None: effective_mode = _detect_mode(mode, env) if effective_mode == "k3d": update(namespace=namespace, env=env, mode=effective_mode, log=log) return target_ns = _registry_namespace(namespace, env) if not _exists("deployment", "registry", target_ns, env=env): update(namespace=namespace, env=env, mode=effective_mode, log=log) return _kubectl( ["-n", target_ns, "rollout", "restart", "deployment/registry"], env=env, timeout=120, check=True, ) _wait_rollout("deployment", "registry", target_ns, env=env) def status( *, namespace: str | None = None, env: dict | None = None, mode: str | None = None, ) -> bool: effective_mode = _detect_mode(mode, env) if effective_mode == "k3d": name = str((env or {}).get("K3D_REGISTRY_NAME") or "prole-registry") reg = _k3d(["registry", "list"], env=env, timeout=30) return _to_bool(reg.returncode == 0 and name in reg.stdout) target_ns = _registry_namespace(namespace, env) dep = _kubectl( ["-n", target_ns, "get", "deployment", "registry", "-o", "jsonpath={.status.readyReplicas}"], env=env, timeout=20, ) svc = _kubectl(["-n", target_ns, "get", "svc", "registry"], env=env, timeout=20) return _to_bool( dep.returncode == 0 and (dep.stdout or "0").strip() not in {"", "0"} and svc.returncode == 0 )