feat(infra): docker_restart 쓰기 도구 추가

보호 컨테이너(home-caddy, home-fail2ban, nanoclaude) 재시작 차단.
MCP 11개 도구 + NanoClaude wrapper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-04-13 15:06:40 +09:00
parent d47c04317c
commit 03e3df058f
4 changed files with 74 additions and 5 deletions
+44 -2
View File
@@ -5,8 +5,8 @@ from __future__ import annotations
from datetime import datetime, timezone
from ..config import validate_host, HOSTS
from ..schemas import DockerStatusResult, DockerLogsResult, ContainerInfo
from .ssh import run_command, SSHError
from ..schemas import DockerStatusResult, DockerLogsResult, ContainerInfo, BaseResult
from .ssh import run_command, run_local, SSHError, _is_local_host
def _now() -> str:
@@ -111,3 +111,45 @@ async def docker_logs(host: str, container: str, lines: int = 50) -> DockerLogsR
stderr=stderr.strip() if stderr else "",
raw=stdout.strip(),
)
# Containers that must NEVER be restarted via this tool
PROTECTED_CONTAINERS = {
"home-caddy", # ingress — 재시작 시 전체 서비스 일시 중단
"home-fail2ban", # 보안
"nanoclaude", # 자기 자신
}
async def docker_restart(host: str, container: str) -> BaseResult:
"""Restart a Docker container. Protected containers are blocked."""
try:
cfg = validate_host("docker_status", host) # same host validation as docker_status
except ValueError as e:
return BaseResult(ok=False, checked_at=_now(), error_type="parse_error", error=str(e))
if container in PROTECTED_CONTAINERS:
return BaseResult(
ok=False, checked_at=_now(),
error_type="command_failed",
error=f"보호된 컨테이너입니다: {container}. 직접 재시작하세요.",
)
docker = cfg.docker_path
cmd = f"{docker} restart {container}"
try:
if _is_local_host(cfg):
stdout, _ = await run_local(cmd, timeout=30)
else:
stdout, _ = await run_command(cfg, cmd, use_sudo=cfg.needs_sudo, timeout=30)
except SSHError as e:
return BaseResult(
ok=False, checked_at=_now(),
error_type=e.error_type, error=str(e),
)
return BaseResult(
ok=True, checked_at=_now(),
warnings=[f"{container} 재시작 완료 (host: {host})"],
)