GRM-17: fix docker mode status detection and systemd template

- systemd template for docker mode now uses Type=oneshot + RemainAfterExit=yes
  so that systemctl is-active returns active when the container is running.
  Previously docker run -d exited immediately, causing systemd to mark the
  service as inactive even though the container was still up.
- grm list now tries multiple container name fallbacks for docker mode:
  1. gitea-runner-{name} (current naming)
  2. gitea-runner-{host} (legacy installs where name defaulted to host)
  3. systemctl is-active gitea-runner@{name} (for installs with fixed template)
- All tests pass, 100% coverage, ruff + pyright clean
This commit is contained in:
Emil Simeonov
2026-06-19 02:47:14 +02:00
parent 12e6ce1601
commit 1bbe3b4f43
2 changed files with 40 additions and 19 deletions
+37 -18
View File
@@ -289,18 +289,44 @@ class RunnerManager:
user=user,
)
)
def _parse_status(stdout: str) -> str:
ansible_noise = (" | CHANGED | ", " | FAILED | ", " | UNREACHABLE | ", "[WARNING]", "ssh:", ">>")
lines = [ln for ln in stdout.splitlines() if ln.strip() and not any(p in ln for p in ansible_noise)]
return lines[-1].strip() if lines else "unknown"
try:
if mode == "docker":
stdout = self._executor.run_ad_hoc(
host,
user,
key,
"shell",
f"docker inspect -f '{{{{.State.Status}}}}' gitea-runner-{name} 2>/dev/null",
become=True,
ask_become_pass=True,
check=False,
)
# Try expected container name first, then host-based fallback for legacy installs
for container_name in (f"gitea-runner-{name}", f"gitea-runner-{host}"):
stdout = self._executor.run_ad_hoc(
host,
user,
key,
"shell",
f"docker inspect -f '{{{{.State.Status}}}}' {container_name} 2>/dev/null",
become=True,
ask_become_pass=True,
check=False,
)
service_status = _parse_status(stdout)
if service_status != "unknown":
docker_map = {"running": "active", "exited": "inactive", "dead": "failed"}
service_status = docker_map.get(service_status, "unknown")
break
else:
# Final fallback: check systemd service (for installs using the fixed template)
stdout = self._executor.run_ad_hoc(
host,
user,
key,
"shell",
f"systemctl is-active gitea-runner@{name} 2>/dev/null",
become=True,
ask_become_pass=True,
check=False,
)
service_status = _parse_status(stdout)
else:
stdout = self._executor.run_ad_hoc(
host,
@@ -312,14 +338,7 @@ class RunnerManager:
ask_become_pass=True,
check=False,
)
# Filter out ansible noise (headers, warnings, SSH messages)
ansible_noise = (" | CHANGED | ", " | FAILED | ", " | UNREACHABLE | ", "[WARNING]", "ssh:", ">>")
lines = [ln for ln in stdout.splitlines() if ln.strip() and not any(p in ln for p in ansible_noise)]
service_status = lines[-1].strip() if lines else "unknown"
# Docker statuses need mapping to systemd vocabulary
if mode == "docker":
docker_map = {"running": "active", "exited": "inactive", "dead": "failed"}
service_status = docker_map.get(service_status, "unknown")
service_status = _parse_status(stdout)
except Exception:
service_status = "unknown"
# Translate known status values