GRM-17: fix: make grm list retrieve runner status correctly
- run_ad_hoc() now raises AnsibleError on non-zero exit, surfacing stderr instead of silently returning empty stdout - list_runners() passes become=True to run_ad_hoc since systemctl is-active requires root privileges - Add i18n translations for ad-hoc failure messages - Add unit test for run_ad_hoc failure case - Update list_runners test to expect become=True - 119 tests, 100% coverage, pyright clean, ruff clean
This commit is contained in:
@@ -109,6 +109,15 @@ class AnsibleExecutor:
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
stderr = proc.stderr.strip() if proc.stderr else ""
|
||||
raise AnsibleError(
|
||||
_(
|
||||
"Ad-hoc command failed on {host}: {stderr}",
|
||||
host=host,
|
||||
stderr=stderr or _("exit code {code}", code=proc.returncode),
|
||||
)
|
||||
)
|
||||
return proc.stdout.strip()
|
||||
|
||||
def _extract_status(self, log_file: Path) -> str | None:
|
||||
|
||||
@@ -474,6 +474,20 @@ TRANSLATIONS: dict[str, dict[str, str]] = {
|
||||
"ru": "Пропустить удаленную очистку и удалить только локальную запись реестра",
|
||||
"zh": "跳过远程清理,仅删除本地注册表条目",
|
||||
},
|
||||
"Ad-hoc command failed on {host}: {stderr}": {
|
||||
"en": "Ad-hoc command failed on {host}: {stderr}",
|
||||
"bg": "Ad-hoc командата неуспешна на {host}: {stderr}",
|
||||
"de": "Ad-hoc-Befehl auf {host} fehlgeschlagen: {stderr}",
|
||||
"ru": "Ad-hoc команда не удалась на {host}: {stderr}",
|
||||
"zh": "Ad-hoc 命令在 {host} 上失败: {stderr}",
|
||||
},
|
||||
"exit code {code}": {
|
||||
"en": "exit code {code}",
|
||||
"bg": "код за изход {code}",
|
||||
"de": "Exit-Code {code}",
|
||||
"ru": "код выхода {code}",
|
||||
"zh": "退出代码 {code}",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -281,7 +281,9 @@ class RunnerManager:
|
||||
key = info.get("key")
|
||||
mode = info.get("mode", "docker")
|
||||
try:
|
||||
stdout = self._executor.run_ad_hoc(host, user, key, "shell", f"systemctl is-active gitea-runner@{name}")
|
||||
stdout = self._executor.run_ad_hoc(
|
||||
host, user, key, "shell", f"systemctl is-active gitea-runner@{name}", become=True
|
||||
)
|
||||
# Filter out ansible noise (SSH warnings etc)
|
||||
lines = [ln for ln in stdout.splitlines() if ln.strip() and not ln.startswith(("[WARNING]", "ssh:"))]
|
||||
service_status = lines[-1].strip() if lines else "unknown"
|
||||
|
||||
@@ -206,3 +206,14 @@ class TestAnsibleExecutorAdHoc:
|
||||
assert result == "ok"
|
||||
cmd = mock_run.call_args.args[0]
|
||||
assert "--become" in cmd
|
||||
|
||||
def test_run_ad_hoc_failure_raises(self, tmp_path: Path) -> None:
|
||||
executor = AnsibleExecutor(log_dir=tmp_path)
|
||||
result_mock = MagicMock()
|
||||
result_mock.stdout = ""
|
||||
result_mock.returncode = 1
|
||||
result_mock.stderr = "SSH timeout"
|
||||
|
||||
with patch("subprocess.run", return_value=result_mock):
|
||||
with pytest.raises(AnsibleError, match="SSH timeout"):
|
||||
executor.run_ad_hoc("10.0.0.1", "ubuntu", None, "shell", "cmd")
|
||||
|
||||
@@ -408,7 +408,7 @@ class TestRunnerManager:
|
||||
assert runners[0]["host"] == "10.0.0.1"
|
||||
assert runners[0]["status"] == "active"
|
||||
mock_executor.run_ad_hoc.assert_called_once_with(
|
||||
"10.0.0.1", "ubuntu", "/key", "shell", "systemctl is-active gitea-runner@r1"
|
||||
"10.0.0.1", "ubuntu", "/key", "shell", "systemctl is-active gitea-runner@r1", become=True
|
||||
)
|
||||
|
||||
def test_list_runners_empty(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user