Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 56s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
356 lines
12 KiB
Python
356 lines
12 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
VERIFIER = ROOT / "ops/runner/check-awoooi-non110-runner-readiness.sh"
|
|
|
|
|
|
def _write_fake_bin(path: Path, name: str, body: str) -> None:
|
|
target = path / name
|
|
target.write_text(body, encoding="utf-8")
|
|
target.chmod(0o755)
|
|
|
|
|
|
def _write_runner_config(path: Path) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(
|
|
"""
|
|
runner:
|
|
capacity: 1
|
|
labels:
|
|
- "awoooi-host:host"
|
|
- "awoooi-ubuntu:docker://192.168.0.110:5000/awoooi/ci-runner:act-22.04"
|
|
""".strip()
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
|
|
def _write_unit(
|
|
path: Path,
|
|
binary_path: Path,
|
|
config_path: Path,
|
|
registration_path: Path,
|
|
) -> None:
|
|
path.write_text(
|
|
f"""
|
|
[Unit]
|
|
ConditionPathExists={registration_path}
|
|
|
|
[Service]
|
|
ExecStart={binary_path} daemon --config {config_path}
|
|
Restart=always
|
|
CPUQuota=200%
|
|
MemoryMax=8G
|
|
TasksMax=512
|
|
NoNewPrivileges=true
|
|
""".strip()
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
|
|
def _write_path_unit(path: Path, registration_path: Path) -> None:
|
|
path.write_text(
|
|
f"""
|
|
[Unit]
|
|
Description=Watch AWOOOI non-110 runner registration metadata
|
|
|
|
[Path]
|
|
PathExists={registration_path}
|
|
Unit=awoooi-non110-runner-autostart.service
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
""".strip()
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
|
|
def _write_keepalive_timer(path: Path) -> None:
|
|
path.write_text(
|
|
"""
|
|
[Unit]
|
|
Description=Periodically verify AWOOOI non-110 runner user service is active
|
|
|
|
[Timer]
|
|
OnBootSec=30s
|
|
OnUnitInactiveSec=60s
|
|
AccuracySec=10s
|
|
Unit=awoooi-non110-runner-keepalive.service
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
""".strip()
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
|
|
def _write_keepalive_service(path: Path) -> None:
|
|
path.write_text(
|
|
"""
|
|
[Unit]
|
|
Description=Keep AWOOOI non-110 runner active while enable sentinel exists
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/systemctl --user daemon-reload
|
|
ExecStart=-/usr/bin/systemctl --user reset-failed awoooi-non110-runner.service
|
|
ExecStart=/usr/bin/systemctl --user enable awoooi-non110-runner.service
|
|
ExecStart=/usr/bin/systemctl --user start awoooi-non110-runner.service
|
|
RemainAfterExit=no
|
|
""".strip()
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
|
|
def _run_verifier(
|
|
tmp_path: Path,
|
|
registration_path: Path,
|
|
*,
|
|
active_service: bool = True,
|
|
unit_target_matches: bool = True,
|
|
unmanaged_runner_container: bool = False,
|
|
keepalive_timer: bool = True,
|
|
keepalive_service_failed: bool = False,
|
|
) -> subprocess.CompletedProcess[str]:
|
|
fake_bin = tmp_path / "bin"
|
|
unit_dir = tmp_path / "units"
|
|
fake_bin.mkdir()
|
|
unit_dir.mkdir()
|
|
_write_fake_bin(
|
|
fake_bin,
|
|
"systemctl",
|
|
f"""#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
if [ "${{1:-}}" = "--user" ]; then shift; fi
|
|
cmd="${{1:-}}"; unit="${{2:-}}"
|
|
case "$cmd" in
|
|
show)
|
|
if [ "${{2:-}}" = "-p" ]; then
|
|
unit="${{1:-}}"
|
|
fi
|
|
if [ -f "{unit_dir}/$unit" ]; then
|
|
if [[ "$unit" == *.path ]]; then
|
|
printf 'LoadState=loaded\\nActiveState=active\\nUnitFileState=enabled\\nMainPID=0\\n'
|
|
exit 0
|
|
fi
|
|
if [[ "$unit" == *.timer ]]; then
|
|
printf 'LoadState=loaded\\nActiveState=active\\nUnitFileState=enabled\\nMainPID=0\\n'
|
|
exit 0
|
|
fi
|
|
if [[ "$unit" == *keepalive.service ]]; then
|
|
printf 'LoadState=loaded\\nActiveState={"failed" if keepalive_service_failed else "inactive"}\\nUnitFileState=static\\nMainPID=0\\nResult={"exit-code" if keepalive_service_failed else "success"}\\nExecMainStatus={"1" if keepalive_service_failed else "0"}\\n'
|
|
exit 0
|
|
fi
|
|
printf 'LoadState=loaded\\nActiveState={"active" if active_service else "inactive"}\\nUnitFileState=disabled\\nMainPID={"1234" if active_service else "0"}\\n'
|
|
exit 0
|
|
fi
|
|
if [ "${{2:-}}" = "-p" ] && [ "${{3:-}}" = "LoadState" ]; then
|
|
printf 'not-found\\n'
|
|
exit 0
|
|
fi
|
|
printf 'LoadState=not-found\\nActiveState=inactive\\nUnitFileState=\\nMainPID=0\\n'
|
|
exit 0
|
|
;;
|
|
cat)
|
|
if [ -f "{unit_dir}/$unit" ]; then cat "{unit_dir}/$unit"; exit 0; fi
|
|
exit 1
|
|
;;
|
|
esac
|
|
exit 1
|
|
""",
|
|
)
|
|
unmanaged_runner_output = (
|
|
"printf 'condescending_wilbur|gitea/act_runner:latest\\n'"
|
|
if unmanaged_runner_container
|
|
else "exit 0"
|
|
)
|
|
_write_fake_bin(
|
|
fake_bin,
|
|
"docker",
|
|
f"""#!/usr/bin/env bash
|
|
if [ "${{1:-}}" = "ps" ]; then
|
|
if printf '%s\\n' "$*" | grep -q 'Image'; then
|
|
{unmanaged_runner_output}
|
|
exit 0
|
|
fi
|
|
exit 0
|
|
fi
|
|
exit 0
|
|
""",
|
|
)
|
|
_write_fake_bin(
|
|
fake_bin,
|
|
"pgrep",
|
|
"""#!/usr/bin/env bash
|
|
exit 1
|
|
""",
|
|
)
|
|
_write_fake_bin(
|
|
fake_bin,
|
|
"ip",
|
|
"""#!/usr/bin/env bash
|
|
if [ "${1:-}" = "-o" ] && [ "${2:-}" = "-4" ] && [ "${3:-}" = "addr" ]; then
|
|
printf '1: lo inet 127.0.0.1/8 scope host lo\\n'
|
|
printf '2: eth0 inet 192.168.0.188/24 brd 192.168.0.255 scope global eth0\\n'
|
|
exit 0
|
|
fi
|
|
exit 1
|
|
""",
|
|
)
|
|
|
|
config_path = tmp_path / "config.yaml"
|
|
binary_path = tmp_path / "act_runner"
|
|
_write_runner_config(config_path)
|
|
binary_path.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
|
|
binary_path.chmod(0o755)
|
|
unit_binary_path = binary_path if unit_target_matches else tmp_path / "other_act_runner"
|
|
unit_config_path = config_path if unit_target_matches else tmp_path / "other_config.yaml"
|
|
_write_unit(
|
|
unit_dir / "awoooi-non110-runner.service",
|
|
unit_binary_path,
|
|
unit_config_path,
|
|
registration_path,
|
|
)
|
|
_write_unit(
|
|
unit_dir / "awoooi-non110-runner-rollback.service",
|
|
unit_binary_path,
|
|
unit_config_path,
|
|
registration_path,
|
|
)
|
|
_write_path_unit(
|
|
unit_dir / "awoooi-non110-runner-autostart.path",
|
|
registration_path,
|
|
)
|
|
if keepalive_timer:
|
|
_write_keepalive_service(unit_dir / "awoooi-non110-runner-keepalive.service")
|
|
_write_keepalive_timer(unit_dir / "awoooi-non110-runner-keepalive.timer")
|
|
|
|
env = {
|
|
**os.environ,
|
|
"PATH": f"{fake_bin}:{os.environ['PATH']}",
|
|
"TARGET_HOST_IP": "",
|
|
"FORBIDDEN_HOST_IPS": "",
|
|
"RUNNER_CONFIG_PATHS": str(config_path),
|
|
"RUNNER_BINARY_PATHS": str(binary_path),
|
|
"RUNNER_SERVICE_NAMES": "awoooi-non110-runner.service",
|
|
"RUNNER_AUTOSTART_PATH_UNIT_NAMES": "awoooi-non110-runner-autostart.path",
|
|
"RUNNER_KEEPALIVE_SERVICE_UNIT_NAMES": "awoooi-non110-runner-keepalive.service",
|
|
"RUNNER_KEEPALIVE_TIMER_UNIT_NAMES": "awoooi-non110-runner-keepalive.timer",
|
|
"ROLLBACK_UNIT_NAMES": "awoooi-non110-runner-rollback.service",
|
|
"RUNNER_REGISTRATION_PATHS": str(registration_path),
|
|
"MAX_HEAVY_PROCESS_COUNT": "0",
|
|
}
|
|
return subprocess.run(
|
|
["bash", str(VERIFIER)],
|
|
check=False,
|
|
env=env,
|
|
text=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
)
|
|
|
|
|
|
def test_non110_readiness_blocks_without_registration_state(tmp_path: Path) -> None:
|
|
result = _run_verifier(tmp_path, tmp_path / ".runner")
|
|
assert result.returncode == 1
|
|
assert "BLOCKER runner_registration_missing" in result.stdout
|
|
assert "AWOOOI_NON110_RUNNER_READY=0" in result.stdout
|
|
assert "raw_runner_registration_read=false" in result.stdout
|
|
assert (
|
|
"safe_next_step=run_register_awoooi_non110_runner_script_without_printing_token_then_autostart_path_will_enable_service_and_rerun_this_verifier"
|
|
in result.stdout
|
|
)
|
|
assert "RUNNER_AUTOSTART_PATH unit=awoooi-non110-runner-autostart.path installed=1" in result.stdout
|
|
assert (
|
|
"RUNNER_AUTOSTART_PATH_WATCH unit=awoooi-non110-runner-autostart.path registration_watch=1 active=1 enabled=1"
|
|
in result.stdout
|
|
)
|
|
assert "READY_AUTOSTART_PATH_COUNT=1" in result.stdout
|
|
assert "RUNNER_KEEPALIVE_TIMER unit=awoooi-non110-runner-keepalive.timer installed=1" in result.stdout
|
|
assert "BLOCKER runner_keepalive_timer_not_ready" not in result.stdout
|
|
assert "BLOCKER runner_keepalive_service_not_ready" not in result.stdout
|
|
|
|
|
|
def test_non110_readiness_accepts_registration_state_presence_without_reading_it(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
registration_path = tmp_path / ".runner"
|
|
registration_path.write_text("secret-token-like-content-not-printed\n", encoding="utf-8")
|
|
result = _run_verifier(tmp_path, registration_path)
|
|
assert result.returncode == 0, result.stdout + result.stderr
|
|
assert "RUNNER_REGISTRATION" in result.stdout
|
|
assert "present=1" in result.stdout
|
|
assert "content_read=false" in result.stdout
|
|
assert "registration_condition=1" in result.stdout
|
|
assert "RUNNER_KEEPALIVE_SERVICE unit=awoooi-non110-runner-keepalive.service installed=1" in result.stdout
|
|
assert "READY_KEEPALIVE_SERVICE_COUNT=1" in result.stdout
|
|
assert "RUNNER_KEEPALIVE_TIMER unit=awoooi-non110-runner-keepalive.timer installed=1" in result.stdout
|
|
assert "READY_KEEPALIVE_TIMER_COUNT=1" in result.stdout
|
|
assert "secret-token-like-content" not in result.stdout
|
|
assert "AWOOOI_NON110_RUNNER_READY=1" in result.stdout
|
|
|
|
|
|
def test_non110_readiness_blocks_failed_keepalive_service(tmp_path: Path) -> None:
|
|
registration_path = tmp_path / ".runner"
|
|
registration_path.write_text("secret-token-like-content-not-printed\n", encoding="utf-8")
|
|
result = _run_verifier(
|
|
tmp_path,
|
|
registration_path,
|
|
keepalive_service_failed=True,
|
|
)
|
|
assert result.returncode == 1
|
|
assert "BLOCKER runner_keepalive_service_failed:awoooi-non110-runner-keepalive.service" in result.stdout
|
|
assert "BLOCKER runner_keepalive_service_not_ready" in result.stdout
|
|
assert "secret-token-like-content" not in result.stdout
|
|
assert "AWOOOI_NON110_RUNNER_READY=0" in result.stdout
|
|
|
|
|
|
def test_non110_readiness_blocks_registered_runner_without_keepalive_timer(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
registration_path = tmp_path / ".runner"
|
|
registration_path.write_text("secret-token-like-content-not-printed\n", encoding="utf-8")
|
|
result = _run_verifier(tmp_path, registration_path, keepalive_timer=False)
|
|
assert result.returncode == 1
|
|
assert "BLOCKER runner_keepalive_timer_not_ready" in result.stdout
|
|
assert "READY_KEEPALIVE_TIMER_COUNT=0" in result.stdout
|
|
assert "secret-token-like-content" not in result.stdout
|
|
assert "AWOOOI_NON110_RUNNER_READY=0" in result.stdout
|
|
|
|
|
|
def test_non110_readiness_blocks_service_target_mismatch(tmp_path: Path) -> None:
|
|
registration_path = tmp_path / ".runner"
|
|
registration_path.write_text("secret-token-like-content-not-printed\n", encoding="utf-8")
|
|
result = _run_verifier(tmp_path, registration_path, unit_target_matches=False)
|
|
assert result.returncode == 1
|
|
assert "BLOCKER runner_service_target_mismatch:awoooi-non110-runner.service" in result.stdout
|
|
assert "RUNNER_SERVICE_TARGETS unit=awoooi-non110-runner.service" in result.stdout
|
|
assert "AWOOOI_NON110_RUNNER_READY=0" in result.stdout
|
|
|
|
|
|
def test_non110_readiness_blocks_unmanaged_act_runner_container(tmp_path: Path) -> None:
|
|
registration_path = tmp_path / ".runner"
|
|
registration_path.write_text("secret-token-like-content-not-printed\n", encoding="utf-8")
|
|
result = _run_verifier(
|
|
tmp_path,
|
|
registration_path,
|
|
unmanaged_runner_container=True,
|
|
)
|
|
assert result.returncode == 1
|
|
assert "UNMANAGED_RUNNER_CONTAINERS=condescending_wilbur" in result.stdout
|
|
assert (
|
|
"BLOCKER unmanaged_runner_containers_present:condescending_wilbur"
|
|
in result.stdout
|
|
)
|
|
assert "secret-token-like-content" not in result.stdout
|