Files
grm/src/gitea_runner_manager/runner_manager.py
T

97 lines
2.8 KiB
Python

"""Core logic for managing Gitea runners."""
from __future__ import annotations
import os
import subprocess
from pathlib import Path
from .exceptions import AnsibleError
class RunnerManager:
"""Orchestrates runner installation and updates."""
def install(
self,
host: str,
user: str,
key: str | None = None,
name: str | None = None,
token: str | None = None,
gitea_url: str = "",
mode: str = "docker",
admin_token: str | None = None,
ask_become_pass: bool = False,
) -> None:
"""Install a runner on a remote host using Ansible."""
if not name:
name = host
if not token:
raise AnsibleError("GITEA_REGISTRATION_TOKEN must be set (or pass --token)")
playbook = Path(__file__).parent.parent.parent / "ansible" / "install-runner.yml"
if not playbook.exists():
raise AnsibleError(f"Playbook not found: {playbook}")
extra_vars = f"registration_token={token} runner_name={name} gitea_url={gitea_url} runner_mode={mode}"
if admin_token:
extra_vars += f" gitea_admin_token={admin_token}"
cmd = [
"ansible-playbook",
str(playbook),
"-i",
f"{host},",
"-u",
user,
"--extra-vars",
extra_vars,
]
if key:
cmd.extend(["--private-key", key])
if ask_become_pass:
cmd.append("--ask-become-pass")
self._run_ansible(cmd)
def update(
self,
host: str,
user: str,
key: str | None = None,
version: str | None = None,
mode: str = "docker",
ask_become_pass: bool = False,
) -> None:
"""Update the gitea_runner binary on a remote host."""
playbook = Path(__file__).parent.parent.parent / "ansible" / "update-runner.yml"
if not playbook.exists():
raise AnsibleError(f"Playbook not found: {playbook}")
cmd = [
"ansible-playbook",
str(playbook),
"-i",
f"{host},",
"-u",
user,
"--extra-vars",
f"runner_mode={mode}",
]
if key:
cmd.extend(["--private-key", key])
if version:
cmd.extend(["--extra-vars", f"gitea_runner_version={version}"])
if ask_become_pass:
cmd.append("--ask-become-pass")
self._run_ansible(cmd)
def _run_ansible(self, cmd: list[str]) -> None:
"""Execute an Ansible command, streaming output."""
env = os.environ.copy()
result = subprocess.run(cmd, env=env, check=False) # noqa: S603
if result.returncode != 0:
raise AnsibleError(f"Ansible failed with exit code {result.returncode}")