Files
awoooi/scripts/backup/tests/test_110_backup_runtime_deploy_playbook.py
Your Name e614f061f7
Some checks failed
CD Pipeline / select-latest-carrier (push) Successful in 49s
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m28s
CD Pipeline / revalidate-deploy-carrier (push) Successful in 27s
CD Pipeline / build-and-deploy (push) Failing after 17m18s
CD Pipeline / revalidate-post-deploy-carrier (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
E2E Health Check / e2e-health (push) Successful in 48s
AI 技術雷達監控 / ai-technology-watch (push) Successful in 1m4s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 0s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 22s
fix(backup): verify host188 recovery end to end
2026-07-18 19:12:42 +08:00

98 lines
3.6 KiB
Python

from __future__ import annotations
from pathlib import Path
import yaml
ROOT = Path(__file__).resolve().parents[3]
PLAYBOOK = ROOT / "infra" / "ansible" / "playbooks" / "110-backup-runtime-deploy.yml"
EXPECTED_FILES = {
"common.sh",
"backup-all.sh",
"backup-awoooi.sh",
"backup-awoooi-frequent.sh",
"backup-clawbot.sh",
"backup-sentry.sh",
"backup-host188-products.sh",
"verify-host188-products-backup.sh",
"verify-host188-products-archive.py",
"check-backup-integrity.sh",
"sync-offsite-backups.sh",
"backup-offsite-readiness-gate.sh",
"verify-offsite-full-sync.sh",
"enforce-latest-only-retention.sh",
}
def test_backup_runtime_deploy_is_fixed_to_host_110_and_fourteen_files() -> None:
plays = yaml.safe_load(PLAYBOOK.read_text(encoding="utf-8"))
assert len(plays) == 1
play = plays[0]
assert play["hosts"] == "host_110"
assert play["gather_facts"] is False
assert play["become"] is True
assert play["serial"] == 1
assert play["any_errors_fatal"] is True
assert play["vars"]["backup_runtime_root"] == "/backup/scripts"
stage1 = set(play["vars"]["backup_runtime_stage1_files"])
stage2 = set(play["vars"]["backup_runtime_stage2_files"])
assert stage1 | stage2 == EXPECTED_FILES
assert not stage1 & stage2
assert play["vars"]["backup_runtime_fault_injection_after_stage1"] is False
def test_backup_runtime_deploy_has_validation_rollback_and_identity_readback() -> None:
source = PLAYBOOK.read_text(encoding="utf-8")
assert 'inventory_hostname == "host_110"' in source
assert 'validate: "/bin/bash -n %s"' in source
assert "backup: true" in source
assert "checksum_algorithm: sha256" in source
assert "rstrip=false" in source
assert "backup_runtime_identity_failed" in source
assert "backup_runtime_stage_identity_failed" in source
assert "backup_runtime_fault_injection_after_stage1" in source
assert "backup_runtime_promotion_failed_and_rolled_back" in source
assert "rescue:" in source
assert "ansible.builtin.slurp:" in source
assert "remote_src: true" in source
assert "backup-health-textfile-exporter.py" in source
assert "changed_when: false" in source
for forbidden in (
"ansible.builtin.service:",
"ansible.builtin.systemd:",
"ansible.builtin.cron:",
"ansible.builtin.shell:",
"ansible.builtin.command:",
"ansible.builtin.git:",
"docker_container",
"kubectl",
):
assert forbidden not in source
def test_fault_injection_occurs_mid_promotion_and_rescue_restores_prior_state() -> None:
play = yaml.safe_load(PLAYBOOK.read_text(encoding="utf-8"))[0]
transaction = next(
task
for task in play["tasks"]
if task["name"] == "Promote the staged backup runtime transaction"
)
block_names = [task["name"] for task in transaction["block"]]
rescue_names = [task["name"] for task in transaction["rescue"]]
assert block_names.index("Promote transaction stage one") < block_names.index(
"Exercise bounded rollback fault injection when explicitly requested"
)
assert block_names.index(
"Exercise bounded rollback fault injection when explicitly requested"
) < block_names.index("Promote transaction stage two")
assert "Restore runtime files that existed before promotion" in rescue_names
assert "Remove runtime files that did not exist before promotion" in rescue_names
assert "Restore the exporter that existed before promotion" in rescue_names
assert rescue_names[-1] == "Fail closed after transactional rollback"