Files
cc-ci/tests/unit/test_warmsnap.py
autonomic-bot 4cc1e15a53 feat(2w): W0.5 WC3 snapshot/restore helper (warmsnap.py)
runner/harness/warmsnap.py: raw per-volume tar of an app's stack volumes while
UNDEPLOYED, under /var/lib/ci-warm/<recipe>/ (meta.json + volumes/<vol>.tar);
one last-good, atomic dir swap; restore clears+untars each volume back. Asserts
undeployed (consistency). Reused by WC1.1 (pre-upgrade keycloak snapshot) + WC5.
+5 unit tests (48 unit pass).

LIVE round-trip PROVEN on warm keycloak: create marker realm -> undeploy ->
snapshot (mariadb+providers vols) -> deploy -> delete marker (mutate DB) ->
undeploy -> restore -> deploy -> marker realm BACK; keycloak healthy. WC3 core.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 00:12:46 +01:00

60 lines
2.3 KiB
Python

"""Unit tests for the WC3 snapshot helper's pure path/meta logic (runner/harness/warmsnap.py).
The docker/tar snapshot+restore round-trip is integration (proven live on cc-ci against a real
keycloak volume, W0.5). Here we cover the layout, meta read, and the has_snapshot completeness check.
"""
from __future__ import annotations
import json
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner"))
from harness import warmsnap # noqa: E402
def test_warm_root_env_override(monkeypatch):
monkeypatch.setenv("CCCI_WARM_ROOT", "/tmp/ci-warm-test")
assert warmsnap.warm_root() == "/tmp/ci-warm-test"
assert warmsnap.app_dir("keycloak") == "/tmp/ci-warm-test/keycloak"
assert warmsnap.meta_path("keycloak") == "/tmp/ci-warm-test/keycloak/meta.json"
assert warmsnap.volumes_dir("keycloak") == "/tmp/ci-warm-test/keycloak/volumes"
def test_warm_root_default(monkeypatch):
monkeypatch.delenv("CCCI_WARM_ROOT", raising=False)
assert warmsnap.warm_root() == "/var/lib/ci-warm"
def test_read_meta_absent(monkeypatch, tmp_path):
monkeypatch.setenv("CCCI_WARM_ROOT", str(tmp_path))
assert warmsnap.read_meta("keycloak") is None
assert warmsnap.has_snapshot("keycloak") is False
def _write_snapshot(tmp_path, recipe, volumes):
appdir = tmp_path / recipe
(appdir / "volumes").mkdir(parents=True)
(appdir / "meta.json").write_text(json.dumps({"recipe": recipe, "volumes": volumes}))
for v in volumes:
(appdir / "volumes" / f"{v}.tar").write_bytes(b"fake")
def test_has_snapshot_complete(monkeypatch, tmp_path):
monkeypatch.setenv("CCCI_WARM_ROOT", str(tmp_path))
_write_snapshot(tmp_path, "keycloak", ["a_mariadb", "a_providers"])
assert warmsnap.has_snapshot("keycloak") is True
meta = warmsnap.read_meta("keycloak")
assert meta["volumes"] == ["a_mariadb", "a_providers"]
def test_has_snapshot_incomplete_missing_tar(monkeypatch, tmp_path):
monkeypatch.setenv("CCCI_WARM_ROOT", str(tmp_path))
# meta lists two volumes but only one tar present -> incomplete -> not usable.
appdir = tmp_path / "keycloak"
(appdir / "volumes").mkdir(parents=True)
(appdir / "meta.json").write_text(json.dumps({"recipe": "keycloak", "volumes": ["a", "b"]}))
(appdir / "volumes" / "a.tar").write_bytes(b"fake")
assert warmsnap.has_snapshot("keycloak") is False