Files
awoooi/scripts/reboot-recovery/tests/test_install_host112_guest_recovery_contract.py
ogt c9bb4bbfc6
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m35s
CD Pipeline / build-and-deploy (push) Failing after 7m35s
CD Pipeline / post-deploy-checks (push) Has been skipped
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 16s
fix(recovery): bind host112 closure artifacts
2026-07-14 12:37:28 +08:00

152 lines
5.5 KiB
Python

from __future__ import annotations
import subprocess
from pathlib import Path
ROOT = Path(__file__).resolve().parents[3]
INSTALLER = ROOT / "scripts/reboot-recovery/install-host112-guest-recovery.sh"
def source() -> str:
return INSTALLER.read_text(encoding="utf-8")
def test_installer_shell_syntax_is_valid() -> None:
result = subprocess.run(
["bash", "-n", str(INSTALLER)],
text=True,
capture_output=True,
check=False,
timeout=10,
)
assert result.returncode == 0, result.stdout + result.stderr
def test_apply_and_rollback_require_safe_control_identity() -> None:
text = source()
assert '--trace-id ID --run-id ID --work-item-id ID' in text
assert 'BLOCKER incomplete_control_identity' in text
assert 'BLOCKER unsafe_control_identity' in text
assert 'BLOCKER installer_control_identity_required' in text
assert '^[A-Za-z0-9][A-Za-z0-9._:@+-]{0,127}$' in text
def test_sudo_policy_has_exact_correlated_apply_and_dry_run_only() -> None:
text = source()
assert "SUDOERS_ARGUMENT_REGEX='^--apply --trace-id " in text
assert "SUDOERS_DRY_RUN_ARGUMENT_REGEX='^--dry-run --trace-id " in text
assert '"$TARGET_USER" "$READINESS_TARGET" "$SUDOERS_ARGUMENT_REGEX"' in text
assert (
'"$TARGET_USER" "$READINESS_TARGET" '
'"$SUDOERS_DRY_RUN_ARGUMENT_REGEX"' in text
)
assert 'SUDO_CORRELATED_APPLY_NOPASSWD' in text
assert 'SUDO_CORRELATED_DRY_RUN_NOPASSWD' in text
assert 'SUDO_LEGACY_UNCORRELATED_APPLY_NOPASSWD' in text
assert 'SUDO_UNSAFE_IDENTITY_NOPASSWD' in text
assert 'SUDO_POLICY_READY' in text
def test_windows99_direct_route_is_fingerprint_bound_and_not_forced() -> None:
text = source()
route = text[
text.index("agent99_direct_authorization_ready() {") : text.index(
"readiness_check_no_write_ready() {"
)
]
assert 'HOST112_AGENT99_SOURCE_ADDRESS:-192.168.0.99' in text
assert 'HOST112_AGENT99_EXPECTED_KEY_FINGERPRINT' in text
assert 'AGENT99_99_DIRECT_ROUTE_READY' in text
assert 'index($1, "command=") == 0' in route
assert 'has_restrict($1)' in route
assert 'ssh-keygen -lf -' in route
assert 'cat "$AUTH_FILE"' not in text
assert 'from="%s",restrict,command="%s --check"' in text
assert 'CONTROL_SOURCE_ADDRESS:-192.168.0.110' in text
def test_apply_is_transactional_and_has_a_verified_rollback() -> None:
text = source()
apply_path = text[text.index("static_source_preflight\n") :]
handler = text[
text.index("handle_apply_failure() {") : text.index(
"static_source_preflight() {"
)
]
assert 'set -Eeuo pipefail' in text
assert 'TRANSACTION_ACTIVE=1' in apply_path
assert "trap 'handle_apply_failure $?' ERR" in apply_path
assert "trap 'handle_apply_failure 130' INT TERM" in apply_path
assert 'restore_from_backup "$BACKUP_DIR"' in handler
assert 'verify_rollback "$BACKUP_DIR"' in handler
assert 'ROLLBACK_VERIFIED=1' in handler
assert 'install_failed_rolled_back_verified' in handler
assert 'cmp -s "$backup_dir/rootfs/${path#/}" "$path"' in text
assert 'timer_was_enabled' in text
assert 'timer_was_active' in text
def test_static_gate_precedes_timer_activation_and_no_oneshot_is_started() -> None:
text = source()
apply_path = text[text.index("static_source_preflight\n") :]
static_gate = apply_path.index("post_install_static_gate\n")
timer_start = apply_path.index(
"systemctl start awoooi-host112-guest-recovery.timer"
)
final_gate = apply_path.index("check\n", timer_start)
receipt = apply_path.index(
'write_install_receipt "installed_timer_activated_recovery_separate"'
)
assert static_gate < timer_start < final_gate < receipt
assert 'systemctl enable awoooi-host112-guest-recovery.timer' in apply_path
assert 'systemctl enable --now awoooi-host112-guest-recovery.timer' not in text
assert 'systemctl start awoooi-host112-guest-recovery.service' not in text
assert "grep -Fq 'TimeoutStartSec=480'" in text
assert "for tool in bash cksum cmp flock" in text
assert "TimeoutStartSec=600" not in text
assert 'INSTALLER_SYNCHRONOUS_RECOVERY_START=0' in text
assert 'RECOVERY_EXECUTION_PERFORMED=0' in text
def test_install_receipt_does_not_claim_a_recovery_run() -> None:
text = source()
receipt = text[
text.index("write_install_receipt() {") : text.index(
"handle_apply_failure() {"
)
]
assert 'schema_version=host112_guest_recovery_install_receipt_v1' in receipt
assert 'install_verified=$install_verified' in receipt
assert 'manager_runtime_write_performed=0' in receipt
assert 'recovery_execution_performed=0' in receipt
assert 'recovery_run_id=none' in receipt
assert 'recovery_receipt_ref=none' in receipt
assert 'agent99_99_direct_runtime_probe=not_started' in receipt
assert 'rollback_attempted=$rollback_attempted' in receipt
assert 'rollback_verified=$rollback_verified' in receipt
def test_check_gate_requires_policy_route_timer_and_no_write_readback() -> None:
text = source()
check = text[text.index("check() {") : text.index("require_root() {")]
for required in (
'SUDO_POLICY_READY',
'AGENT99_99_DIRECT_ROUTE_READY',
'READINESS_NO_WRITE_READY',
'TIMER_ENABLED',
'TIMER_ACTIVE',
'CHECK_GATE_READY',
):
assert required in check
assert 'runtime_write_performed=0' in text
assert 'manager_runtime_write_performed=0' in text
assert 'receipt_write_performed=0' in text