Each SSE log-viewer or job-log stream holds a thread for its full lifetime. With --threads 8, a handful of open browser tabs could exhaust the pool. 32 keeps the same single-process scheduler invariant (_claim_lock in job_worker is process-local) while giving SSE plenty of headroom on the test box's user count. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
230 lines
9 KiB
Python
230 lines
9 KiB
Python
import os
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
DEPLOY = ROOT / "deploy"
|
|
|
|
|
|
WEB_UNIT = DEPLOY / "files/usr/local/lib/systemd/system/left4me-web.service"
|
|
SERVER_UNIT = DEPLOY / "files/usr/local/lib/systemd/system/left4me-server@.service"
|
|
GLOBAL_REFRESH_SERVICE = DEPLOY / "files/usr/local/lib/systemd/system/left4me-refresh-global-overlays.service"
|
|
GLOBAL_REFRESH_TIMER = DEPLOY / "files/usr/local/lib/systemd/system/left4me-refresh-global-overlays.timer"
|
|
SYSTEMCTL_HELPER = DEPLOY / "files/usr/local/libexec/left4me/left4me-systemctl"
|
|
JOURNALCTL_HELPER = DEPLOY / "files/usr/local/libexec/left4me/left4me-journalctl"
|
|
SUDOERS = DEPLOY / "files/etc/sudoers.d/left4me"
|
|
HOST_ENV = DEPLOY / "templates/etc/left4me/host.env"
|
|
WEB_ENV_TEMPLATE = DEPLOY / "templates/etc/left4me/web.env.template"
|
|
DEPLOY_SCRIPT = DEPLOY / "deploy-test-server.sh"
|
|
|
|
|
|
def test_global_unit_files_exist_at_product_level_paths():
|
|
assert WEB_UNIT.is_file()
|
|
assert SERVER_UNIT.is_file()
|
|
|
|
|
|
def test_web_unit_contains_required_runtime_contract():
|
|
unit = WEB_UNIT.read_text()
|
|
|
|
assert "User=left4me" in unit
|
|
assert "Group=left4me" in unit
|
|
assert "WorkingDirectory=/opt/left4me" in unit
|
|
assert "Environment=PATH=/opt/left4me/.venv/bin:" in unit
|
|
assert "EnvironmentFile=/etc/left4me/host.env" in unit
|
|
assert "EnvironmentFile=/etc/left4me/web.env" in unit
|
|
assert "ExecStart=/opt/left4me/.venv/bin/gunicorn" in unit
|
|
assert "--workers 1" in unit
|
|
assert "--threads 32" in unit
|
|
assert "NoNewPrivileges=true" not in unit
|
|
assert "PrivateTmp=true" not in unit
|
|
assert "ProtectSystem=full" in unit
|
|
assert "ReadWritePaths=/var/lib/left4me" in unit
|
|
assert "MountFlags=shared" in unit
|
|
|
|
|
|
def test_server_unit_contains_required_runtime_contract():
|
|
unit = SERVER_UNIT.read_text()
|
|
|
|
assert "User=left4me" in unit
|
|
assert "Group=left4me" in unit
|
|
assert "EnvironmentFile=/etc/left4me/host.env" in unit
|
|
assert "EnvironmentFile=/var/lib/left4me/instances/%i/instance.env" in unit
|
|
assert "WorkingDirectory=/var/lib/left4me/runtime/%i/merged/left4dead2" in unit
|
|
assert "ExecStart=/var/lib/left4me/installation/srcds_run" in unit
|
|
assert "$L4D2_ARGS" in unit
|
|
assert "${L4D2_ARGS}" not in unit
|
|
assert "NoNewPrivileges=true" in unit
|
|
assert "PrivateTmp=true" in unit
|
|
assert "PrivateDevices=true" in unit
|
|
assert "ProtectHome=true" in unit
|
|
assert "ProtectSystem=strict" in unit
|
|
assert "ReadOnlyPaths=/var/lib/left4me/installation /var/lib/left4me/overlays" in unit
|
|
assert "ReadWritePaths=/var/lib/left4me/runtime/%i" in unit
|
|
assert "RestrictSUIDSGID=true" in unit
|
|
assert "LockPersonality=true" in unit
|
|
|
|
|
|
def _fake_command(tmp_path, command_name):
|
|
marker = tmp_path / f"{command_name}.args"
|
|
command = tmp_path / command_name
|
|
command.write_text(f"#!/bin/sh\nprintf '%s\n' \"$*\" > '{marker}'\nexit 0\n")
|
|
command.chmod(0o755)
|
|
return marker
|
|
|
|
|
|
def _env_with_fake_commands(tmp_path):
|
|
env = os.environ.copy()
|
|
env["PATH"] = f"{tmp_path}{os.pathsep}{env.get('PATH', '')}"
|
|
return env
|
|
|
|
|
|
def test_helpers_use_fixed_system_tool_paths_not_sudo_path():
|
|
systemctl = SYSTEMCTL_HELPER.read_text()
|
|
journalctl = JOURNALCTL_HELPER.read_text()
|
|
|
|
assert "command -v systemctl" not in systemctl
|
|
assert "command -v journalctl" not in journalctl
|
|
assert "/bin/systemctl" in systemctl or "/usr/bin/systemctl" in systemctl
|
|
assert "/bin/journalctl" in journalctl or "/usr/bin/journalctl" in journalctl
|
|
|
|
|
|
def test_systemctl_helper_passes_shell_syntax_check_and_rejects_bad_args(tmp_path):
|
|
subprocess.run(["sh", "-n", str(SYSTEMCTL_HELPER)], check=True)
|
|
marker = _fake_command(tmp_path, "systemctl")
|
|
|
|
for args in [
|
|
["bad/action", "alpha"],
|
|
["start", ""],
|
|
["start", ".hidden"],
|
|
["start", "bad..name"],
|
|
["start", "bad/name"],
|
|
["start", "bad\\name"],
|
|
["start", "bad name"],
|
|
]:
|
|
result = subprocess.run(["sh", str(SYSTEMCTL_HELPER), *args], env=_env_with_fake_commands(tmp_path), check=False)
|
|
assert result.returncode != 0
|
|
assert not marker.exists()
|
|
|
|
script = SYSTEMCTL_HELPER.read_text()
|
|
assert 'unit="left4me-server@${name}.service"' in script
|
|
assert 'start) exec "$systemctl" start "$unit"' in script
|
|
assert 'stop) exec "$systemctl" stop "$unit"' in script
|
|
assert "--property=ActiveState" in script
|
|
assert "--property=SubState" in script
|
|
|
|
|
|
def test_journalctl_helper_passes_shell_syntax_check_and_rejects_bad_args(tmp_path):
|
|
subprocess.run(["sh", "-n", str(JOURNALCTL_HELPER)], check=True)
|
|
marker = _fake_command(tmp_path, "journalctl")
|
|
|
|
for args in [
|
|
["../evil", "--lines", "25", "--no-follow"],
|
|
["alpha", "--bad", "25", "--no-follow"],
|
|
["alpha", "--lines", "not-number", "--no-follow"],
|
|
["alpha", "--lines", "25", "--bad-follow"],
|
|
["bad/name", "--lines", "25", "--no-follow"],
|
|
]:
|
|
result = subprocess.run(["sh", str(JOURNALCTL_HELPER), *args], env=_env_with_fake_commands(tmp_path), check=False)
|
|
assert result.returncode != 0
|
|
assert not marker.exists()
|
|
|
|
script = JOURNALCTL_HELPER.read_text()
|
|
assert 'unit="left4me-server@${name}.service"' in script
|
|
assert 'exec "$journalctl" -u "$unit" -n "$lines" -o cat "$follow_arg"' in script
|
|
assert 'exec "$journalctl" -u "$unit" -n "$lines" -o cat' in script
|
|
|
|
|
|
def test_sudoers_allows_only_left4me_helpers_not_raw_system_tools():
|
|
sudoers = SUDOERS.read_text()
|
|
|
|
assert (
|
|
"left4me ALL=(root) NOPASSWD: "
|
|
"/usr/local/libexec/left4me/left4me-systemctl *"
|
|
) in sudoers
|
|
assert (
|
|
"left4me ALL=(root) NOPASSWD: "
|
|
"/usr/local/libexec/left4me/left4me-journalctl *"
|
|
) in sudoers
|
|
assert "/bin/systemctl" not in sudoers
|
|
assert "/usr/bin/systemctl" not in sudoers
|
|
assert "/bin/journalctl" not in sudoers
|
|
assert "/usr/bin/journalctl" not in sudoers
|
|
|
|
|
|
def test_env_templates_contain_required_defaults():
|
|
host_env = HOST_ENV.read_text()
|
|
assert "Deployment units use fixed /var/lib/left4me paths" in host_env
|
|
assert host_env.endswith("LEFT4ME_ROOT=/var/lib/left4me\n")
|
|
assert WEB_ENV_TEMPLATE.read_text() == (
|
|
"DATABASE_URL=sqlite:////var/lib/left4me/left4me.db\n"
|
|
"SECRET_KEY=replace-with-generated-secret\n"
|
|
"JOB_WORKER_THREADS=4\n"
|
|
)
|
|
|
|
|
|
def test_deploy_script_has_safe_defaults_and_preserves_state() -> None:
|
|
script = DEPLOY_SCRIPT.read_text()
|
|
|
|
assert "useradd --system --home-dir /var/lib/left4me" in script
|
|
assert "/var/lib/left4me/installation" in script
|
|
assert "/var/lib/left4me/overlays" in script
|
|
assert "/var/lib/left4me/instances" in script
|
|
assert "/var/lib/left4me/runtime" in script
|
|
assert "tar" in script
|
|
assert "--exclude .venv" in script
|
|
assert "--exclude .claude" in script
|
|
assert "pip install -e /opt/left4me/l4d2host -e /opt/left4me/l4d2web" in script
|
|
assert "systemctl enable --now left4me-web.service" in script
|
|
assert "for attempt in" in script
|
|
assert "/opt/left4me/.venv" in script
|
|
assert "visudo -cf /etc/sudoers.d/left4me" in script
|
|
assert "if [ ! -f /etc/left4me/web.env ]" in script
|
|
assert ". /etc/left4me/web.env\n" not in script
|
|
assert "run_left4me_with_env" in script
|
|
assert "LEFT4ME_ADMIN_USERNAME" in script
|
|
assert "LEFT4ME_ADMIN_PASSWORD" in script
|
|
assert "user already exists" in script
|
|
assert "deploy/files" in script
|
|
|
|
|
|
def test_deploy_script_does_not_recurse_into_runtime_state_mounts() -> None:
|
|
script = DEPLOY_SCRIPT.read_text()
|
|
|
|
assert "$sudo_cmd chown -R left4me:left4me /var/lib/left4me" not in script
|
|
assert "$sudo_cmd chown left4me:left4me \\" in script
|
|
assert "/var/lib/left4me/runtime \\" in script
|
|
assert "$sudo_cmd chown -R left4me:left4me /opt/left4me" in script
|
|
|
|
|
|
def test_deploy_script_runs_migrations_before_app_initialization() -> None:
|
|
script = DEPLOY_SCRIPT.read_text()
|
|
|
|
assert "alembic -c /opt/left4me/l4d2web/alembic.ini upgrade head" in script
|
|
assert "from l4d2web.app import create_app; create_app()" not in script
|
|
|
|
|
|
def test_deploy_script_shell_syntax() -> None:
|
|
subprocess.run(["sh", "-n", str(DEPLOY_SCRIPT)], check=True)
|
|
|
|
|
|
def test_global_refresh_timer_units_exist_and_enqueue_only():
|
|
service = GLOBAL_REFRESH_SERVICE.read_text()
|
|
timer = GLOBAL_REFRESH_TIMER.read_text()
|
|
|
|
assert "User=left4me" in service
|
|
assert "EnvironmentFile=/etc/left4me/host.env" in service
|
|
assert "EnvironmentFile=/etc/left4me/web.env" in service
|
|
assert "flask --app l4d2web.app:create_app refresh-global-overlays" in service
|
|
assert "OnCalendar=daily" in timer
|
|
assert "Persistent=true" in timer
|
|
assert "WantedBy=timers.target" in timer
|
|
|
|
|
|
def test_deploy_script_installs_and_enables_global_refresh_timer():
|
|
script = DEPLOY_SCRIPT.read_text()
|
|
|
|
assert "/var/lib/left4me/global_overlay_cache" in script
|
|
assert "left4me-refresh-global-overlays.service" in script
|
|
assert "left4me-refresh-global-overlays.timer" in script
|
|
assert "systemctl enable --now left4me-refresh-global-overlays.timer" in script
|