mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-10-08 22:46:41 +00:00
feat(oci): recreate coordinated stacks from saved state
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
"""The coordinated Recreate path must remain distinct from Update."""
|
||||
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT / "remote"))
|
||||
|
||||
import oci_stack_native as native
|
||||
|
||||
|
||||
DIGEST = "sha256:" + "a" * 64
|
||||
MEMBER = {
|
||||
"vmid": 138,
|
||||
"installation_id": "blinko-installation",
|
||||
"template": {"id": "blinko", "container_contract": {"image": {"reference": "blinkospace/blinko:latest"}}},
|
||||
"deployment": {"mounts": []},
|
||||
"observed": {"config_sha256": "saved-config", "resolved_registry_digest": DIGEST,
|
||||
"image": {"architecture": "amd64", "os": "linux", "defaults": {}}},
|
||||
"stack": {"deployment": {"services": [{"vmid": 138, "name": "Blinko",
|
||||
"healthcheck": {"type": "running", "timeout_seconds": 120}}]}},
|
||||
}
|
||||
|
||||
|
||||
class StackRecreateV1Tests(unittest.TestCase):
|
||||
def adapter(self):
|
||||
plan = {"operation": "recreate", "primary_vmid": 138, "members": [MEMBER]}
|
||||
return native.NativeAdapter(Path("/registry"), Path("/journal"), plan)
|
||||
|
||||
def test_prepare_resolves_the_saved_digest_and_builds_an_unchanged_proposal(self):
|
||||
adapter = self.adapter()
|
||||
image = {"architecture": "amd64", "os": "linux", "defaults": {}}
|
||||
with patch.object(native.instances, "read", return_value={}), \
|
||||
patch.object(native.instances, "write"), \
|
||||
patch.object(native.instances, "location", return_value=Path("/registry/138.json")), \
|
||||
patch.object(native.instances, "command", return_value=b"arch: amd64\n"), \
|
||||
patch.object(native, "resolve_archive", return_value=(Path("/cache/blinko.tar"), DIGEST)) as resolve, \
|
||||
patch.object(native, "image_from_archive", return_value=image):
|
||||
prepared = adapter.prepare(MEMBER, "recreate")
|
||||
|
||||
resolve.assert_called_once_with(MEMBER, b"arch: amd64\n", required_digest=DIGEST)
|
||||
self.assertEqual(prepared["digest"], DIGEST)
|
||||
self.assertEqual(prepared["proposal"]["operation"], "recreate")
|
||||
self.assertEqual(prepared["proposal"]["candidate"], MEMBER)
|
||||
self.assertEqual(prepared["proposal"]["base_config_sha256"], "saved-config")
|
||||
|
||||
def test_replace_passes_the_recreate_operation_and_proposal_to_every_member(self):
|
||||
adapter = self.adapter()
|
||||
prepared = {"archive": "/cache/blinko.tar", "digest": DIGEST,
|
||||
"proposal": {"operation": "recreate", "candidate": MEMBER,
|
||||
"base_config_sha256": "saved-config"}}
|
||||
with patch.object(adapter, "validate"), \
|
||||
patch.object(adapter, "state", return_value={"backups": {"138": {"archive": "/backup"}}}), \
|
||||
patch.object(native.member_tx, "apply") as apply:
|
||||
adapter.replace(138, prepared, "transaction-id")
|
||||
|
||||
self.assertEqual(apply.call_args.args[3], "recreate")
|
||||
self.assertEqual(apply.call_args.kwargs["proposal"], prepared["proposal"])
|
||||
self.assertEqual(apply.call_args.kwargs["registry_digest"], DIGEST)
|
||||
self.assertIn("Recreating", apply.call_args.kwargs["progress"])
|
||||
|
||||
def test_an_unknown_stack_operation_is_rejected_before_the_stack_is_touched(self):
|
||||
with self.assertRaises(ValueError):
|
||||
native.run(138, operation="not-a-lifecycle-operation")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user