97 lines
2.8 KiB
Python
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}")
|