Files
Unraid-AppOps-Gateway-Public/backend/tests/test_registered_legacy_followup_controller.py
T

168 lines
7.1 KiB
Python

from __future__ import annotations
from types import SimpleNamespace
import pytest
from test_deploy_broker import deploy_module as _deploy_fixture
from test_hub_component_transport import controller as _controller_fixture
@pytest.fixture
def deploy_module():
return _deploy_fixture.__wrapped__()
@pytest.fixture
def controller(monkeypatch):
return _controller_fixture.__wrapped__(monkeypatch)
@pytest.mark.parametrize("mode", ["deploy", "rollback"])
def test_original_git_objects_are_bound_before_identity_reads(deploy_module, monkeypatch, mode):
monkeypatch.delenv("APPOPS_REGISTERED_LEGACY_REQUEST_ID", raising=False)
monkeypatch.delenv("GIT_NO_REPLACE_OBJECTS", raising=False)
assert deploy_module.bind_registered_legacy_request({}, mode) == ""
assert deploy_module.os.environ["GIT_NO_REPLACE_OBJECTS"] == "1"
def test_known_registered_restore_keeps_verified_revision_and_fresh_runtime_ids(deploy_module):
prior_revision = "a" * 40
restored_artifacts = {
"containers": {
"quiz-monitor-quiz-server-1": {
"container_id": "b" * 64,
"image_id": "sha256:" + "c" * 64,
}
},
"registered_legacy": {"requestId": "restored-request", "revision": prior_revision},
}
restored_receipt = {"revision": prior_revision, "containers": restored_artifacts["containers"]}
project = {
"_registered_legacy_restored": True,
"_registered_legacy_restored_revision": prior_revision,
"_registered_legacy_restored_artifacts": restored_artifacts,
"_registered_legacy_restored_receipt": restored_receipt,
}
result = deploy_module.resolve_failed_live_state(
{"live_revision": prior_revision, "live_status": "healthy"},
{"revision": prior_revision, "legacy_provenance": False, "registered_legacy": {}},
project,
production_started=True,
failure_stage="verification",
restore_error=None,
)
assert result["live_revision"] == prior_revision
assert result["live_status"] == "healthy"
assert result["live_legacy_provenance"] is False
assert result["live_artifacts"] == restored_artifacts
assert result["live_receipt"] == restored_receipt
def test_failed_known_registered_restore_keeps_provenance_unknown(deploy_module):
prior_revision = "a" * 40
result = deploy_module.resolve_failed_live_state(
{"live_revision": prior_revision, "live_status": "healthy"},
{"revision": prior_revision, "legacy_provenance": False, "registered_legacy": {}},
{},
production_started=True,
failure_stage="verification",
restore_error=RuntimeError("restore failed"),
)
assert result["live_status"] == "unknown"
assert result["live_artifacts"] == {}
assert result["live_receipt"] == {}
def test_known_restore_source_callback_precedes_verification_and_state_binding(
deploy_module, monkeypatch
):
previous_revision = "a" * 40
failed_revision = "d" * 40
image_ids = {"quiz-monitor-quiz-server-1": "sha256:" + "c" * 64}
restored_receipt = {"revision": previous_revision, "build": {"revision": previous_revision}}
artifacts = {"containers": {}, "registered_legacy": {"revision": previous_revision}}
events = []
project = {}
def core_restore(_repository, _project, _snapshot, _failed, **kwargs):
events.append("signed-preimage-verified")
restore_source = kwargs.get("restore_source")
assert callable(restore_source), "known restore requires a source callback after signed validation"
restore_source(previous_revision)
events.append("restored-runtime-signed")
return {"revision": previous_revision, "artifacts": artifacts,
"imageIDs": image_ids, "liveReceipt": restored_receipt}
def source_restore(_project, _repository, revision):
assert revision == previous_revision
events.append("prior-source-restored")
def verify(_project, metadata, *, expected_image_ids):
assert metadata["revision"] == previous_revision
assert expected_image_ids == image_ids
events.append("health-and-provenance-verified")
return restored_receipt
monkeypatch.setattr(deploy_module, "read_state", lambda _project: {})
monkeypatch.setattr(deploy_module, "_registered_legacy_receipt_key", lambda: b"k" * 32)
monkeypatch.setattr(deploy_module, "_load_registered_legacy_adoption", lambda: SimpleNamespace(
restore_deployment_snapshot=core_restore
))
monkeypatch.setattr(deploy_module, "restore_live_source", source_restore)
monkeypatch.setattr(deploy_module, "validate_recorded_receipt", lambda *_args: restored_receipt["build"])
monkeypatch.setattr(deploy_module, "verify_deployment", verify)
deploy_module.restore_compose_snapshot(
project,
{"revision": previous_revision, "legacy_provenance": False, "registered_legacy": {}},
"jens/quiz-monitor", failed_revision,
)
assert events == ["signed-preimage-verified", "prior-source-restored",
"restored-runtime-signed", "health-and-provenance-verified"]
assert project["_registered_legacy_restored"] is True
assert project["_registered_legacy_restored_revision"] == previous_revision
assert project["_registered_legacy_restored_receipt"] == restored_receipt
@pytest.mark.parametrize("receipt_matches", [True, False])
def test_typed_rollback_worker_supplies_fixed_source_and_provenance_verifiers(
controller, monkeypatch, receipt_matches
):
import sys
module, projects = controller
repository = "jens/quiz-monitor"
previous_revision = "a" * 40
receipt = {"revision": previous_revision, "build": {"revision": previous_revision}}
project = {"slug": "quiz-monitor", "source_dir": "/fixed/source"}
projects[repository] = project
calls = []
def rollback(_payload, **kwargs):
kwargs["restore_source"](previous_revision)
kwargs["verify_restored"]({"revision": previous_revision, "liveReceipt": receipt,
"imageIDs": {"quiz": "immutable-image"}})
calls.append("state-cas")
monkeypatch.setitem(sys.modules, "registered_legacy_adoption", SimpleNamespace(
rollback=rollback, read_registered_state=lambda *_a: ({}, None),
RegisteredLegacyAdoptionError=ValueError,
record_worker_failure=lambda *_a, **_k: calls.append("failed"),
))
monkeypatch.setitem(sys.modules, "deploy", SimpleNamespace(
restore_live_source=lambda selected, repo, revision: calls.append(
("source", selected, repo, revision)),
validate_recorded_receipt=lambda selected, raw, repo, revision: receipt["build"],
verify_deployment=lambda selected, build, **kwargs: calls.append("verified") or (
receipt if receipt_matches else {**receipt, "revision": "f" * 40}
),
))
module._run_registered_legacy_rollback({
"repository": repository, "requestId": "11111111-1111-4111-8111-111111111111",
}, b"k" * 32)
assert calls == [("source", project, repository, previous_revision), "verified",
"state-cas" if receipt_matches else "failed"]