Files
Unraid-AppOps-Gateway-Public/backend/tests/test_media_codec_dashboard_deployment_reconciliation.py

190 lines
8.9 KiB
Python

from types import SimpleNamespace
from backend.app.services.media_codec_dashboard_deployment_reconciliation import (
MediaCodecDashboardDeploymentReconciliation,
)
class FakeResponse:
def __init__(self, payload):
self.payload = payload
def json(self):
return self.payload
class FakePortainer:
def __init__(self, exit_code=0):
self.exit_code = exit_code
self.calls = []
def get_container_status(self, name):
assert name == "gitea-deploy-control"
return {
"status": "ok",
"container": {
"id": "controller-id",
"name": "gitea-deploy-control",
"state": "running",
},
}
def _config(self):
return SimpleNamespace(endpoint_id="3")
def _request(self, method, path, **kwargs):
self.calls.append((method, path, kwargs))
if path.endswith("/containers/controller-id/exec"):
return FakeResponse({"Id": "exec-1"})
if path.endswith("/exec/exec-1/start"):
return FakeResponse({})
if path.endswith("/exec/exec-1/json"):
return FakeResponse({"Running": False, "ExitCode": self.exit_code})
raise AssertionError(path)
def test_embedded_reconciliation_script_is_valid_python():
fake = FakePortainer()
MediaCodecDashboardDeploymentReconciliation(fake).run()
script = fake.calls[0][2]["json"]["Cmd"][2]
compile(script, "media-codec-dashboard-reconcile", "exec")
def test_reconciliation_derives_the_verified_live_revision_from_runtime_evidence():
fake = FakePortainer()
result = MediaCodecDashboardDeploymentReconciliation(fake).run()
assert result == {
"status": "reconciled",
"repository": "jens/media-codec-dashboard",
"container": "Media-Codec-Dashboard",
}
create = fake.calls[0]
command = create[2]["json"]["Cmd"]
assert command[:2] == ["python3", "-c"]
assert command[3:] == [
"jens/media-codec-dashboard",
"Media-Codec-Dashboard",
]
script = command[2]
# The mutable registry must identify the protected volume's fixed config.
assert "/controller-hub-releases/controller-config/projects.json" in script
assert "/srv/example/appdata/gitea-deploy-runners/controller/projects.json" not in script
assert "/mnt/cache/appdata/gitea-deploy-runners/state" in script
assert "/srv/example/appdata/gitea-deploy-runners/deploy.lock" not in script
assert "/mnt/cache/appdata/gitea-deploy-runners/deploy.lock" in script
assert "os.path.samefile(registry_path, host_registry_path)" in script
assert '"/app/data": "/srv/example/appdata/media-codec-dashboard/data"' in script
assert '"/app/data/quality-runtime": "/srv/example/appdata/tdarr/logs/media-codec-dashboard-quality-audit"' in script
assert '"/run/secrets": "/srv/example/appdata/media-codec-dashboard/secrets"' in script
assert '"/tdarr-output": "/srv/example/Media"' in script
assert '"/tdarr-db"' not in script
# Never freeze a one-time recovery helper to a historical deployment SHA.
assert "971df2cc305c1b447b4feb255d4e9fda871315c3" not in script
assert "adf53604739d4247193a7b5bfeb8ad8981d9d359" not in script
assert "live_revision, stale_revision" not in script
# The immutable revision must be proven independently by both the running
# container label and the immutable image label, then resolved in Gitea.
assert 'container_revision = str(labels.get("org.opencontainers.image.revision") or "")' in script
assert 'image_revision = str(image_labels.get("org.opencontainers.image.revision") or "")' in script
assert "container_revision != image_revision" in script
assert 're.fullmatch(r"[0-9a-f]{40}", live_revision)' in script
assert 'git_run("rev-parse", f"{live_revision}^{{commit}}")' in script
assert 'git_run("merge-base", "--is-ancestor", live_revision, main_revision)' in script
# The stale controller revision is read from durable state. Recovery is
# allowed only when that recorded live revision is a real older ancestor of
# the currently running immutable image, never for arbitrary drift.
assert 'recorded_live = str(state.get("live_revision") or state.get("revision") or "")' in script
assert 're.fullmatch(r"[0-9a-f]{40}", recorded_live)' in script
assert 'git_run("merge-base", "--is-ancestor", recorded_live, live_revision)' in script
assert 'recorded_live == live_revision' in script
assert '"live_legacy_provenance": True' in script
assert create[2]["json"]["AttachStdout"] is False
assert create[2]["json"]["AttachStderr"] is False
def test_reconciliation_distinguishes_failed_attempt_from_recorded_live_revision():
fake = FakePortainer()
MediaCodecDashboardDeploymentReconciliation(fake).run()
script = fake.calls[0][2]["json"]["Cmd"][2]
# Controller schema v3 keeps the real live revision while top-level status
# describes the most recent deployment attempt. A failed forward attempt is
# therefore recoverable when the independently verified runtime still equals
# recorded_live and the failed attempt is a distinct valid descendant.
assert 'recorded_live_status = str(state.get("live_status") or "")' in script
assert 'last_attempt = dict(state.get("last_attempt") or {})' in script
assert 'attempt_revision = str(last_attempt.get("revision") or "")' in script
assert 'attempt_status = str(last_attempt.get("status") or "")' in script
assert "current_live_failed_baseline = (" in script
assert 'recorded_status == "failed"' in script
assert 'recorded_live_status == "healthy" or current_live_unknown_snapshot_baseline' in script
assert 'git_run("merge-base", "--is-ancestor", live_revision, attempt_revision)' in script
assert 'git_run("merge-base", "--is-ancestor", attempt_revision, main_revision)' in script
def test_reconciliation_accepts_exact_current_legacy_snapshot_failure_only_with_matching_artifacts():
fake = FakePortainer()
MediaCodecDashboardDeploymentReconciliation(fake).run()
script = fake.calls[0][2]["json"]["Cmd"][2]
assert "current_live_unknown_snapshot_baseline = (" in script
assert 'recorded_live_status == "unknown"' in script
assert 'state.get("live_legacy_provenance") is True' in script
assert 'attempt.get("message") == "Existing production containers require a valid healthy live deployment state"' in script
assert 'attempt.get("updated_at_epoch") == state.get("updated_at_epoch")' in script
assert 'current_receipt == {}' in script
assert 'set(current_artifacts) == {"compose_sha256", "containers"}' in script
assert 'set(current_artifact_containers) == {expected_container}' in script
assert 'all(current_stored_artifact.get(field) == container_artifact.get(field) for field in current_immutable_fields)' in script
assert 'current_live_failed_baseline = (' in script
assert 'recorded_live_status == "healthy" or current_live_unknown_snapshot_baseline' in script
def test_reconciliation_accepts_only_an_internally_consistent_stale_success_baseline():
fake = FakePortainer()
MediaCodecDashboardDeploymentReconciliation(fake).run()
script = fake.calls[0][2]["json"]["Cmd"][2]
# A previously successful controller baseline may legitimately lag behind
# an independently verified newer immutable runtime. Accept that drift only
# when the old state is internally self-consistent: healthy live status and
# a successful last attempt for exactly the recorded old live revision.
assert "stale_success_baseline = (" in script
assert 'recorded_status == "success"' in script
assert 'recorded_live_status == "healthy"' in script
assert 'attempt_status == "success"' in script
assert "attempt_revision == recorded_live" in script
assert 'stale_failed_attempt = recorded_status == "failed"' in script
assert "if not (stale_success_baseline or stale_failed_attempt):" in script
assert 'git_run("merge-base", "--is-ancestor", recorded_live, live_revision)' in script
def test_reconciliation_refuses_wrong_live_mount_topology():
result = MediaCodecDashboardDeploymentReconciliation(FakePortainer(exit_code=48)).run()
assert result == {
"status": "validation_failed",
"reason": "live Media Codec Dashboard mount topology differs from the verified runtime",
}
def test_reconciliation_refuses_unknown_state_drift():
result = MediaCodecDashboardDeploymentReconciliation(FakePortainer(exit_code=52)).run()
assert result == {
"status": "validation_failed",
"reason": "controller state drift is not the exact known recoverable state",
}
def test_reconciliation_refuses_wrong_image_revision_label():
result = MediaCodecDashboardDeploymentReconciliation(FakePortainer(exit_code=51)).run()
assert result == {
"status": "validation_failed",
"reason": "live Media Codec Dashboard image revision label does not match the verified runtime",
}