fix(device-edge): reconcile runtime modes safely
This commit is contained in:
@@ -92,7 +92,13 @@ class DeviceEdgeVpsArtifactTest(unittest.TestCase):
|
||||
|
||||
def test_builders_are_deterministic_narrow_and_secret_free(self):
|
||||
self.require_runtime_cache()
|
||||
for phase in ("foundation", "backhaul", "relay", "core-channel"):
|
||||
for phase in (
|
||||
"foundation",
|
||||
"runtime-reconciliation",
|
||||
"backhaul",
|
||||
"relay",
|
||||
"core-channel",
|
||||
):
|
||||
with self.subTest(phase=phase), tempfile.TemporaryDirectory(
|
||||
prefix=f"nodedc-vps-{phase}-"
|
||||
) as directory:
|
||||
@@ -164,7 +170,13 @@ class DeviceEdgeVpsArtifactTest(unittest.TestCase):
|
||||
old_inbox = RUNNER.INBOX_ROOT
|
||||
RUNNER.INBOX_ROOT = inbox
|
||||
try:
|
||||
for phase in ("foundation", "backhaul", "relay", "core-channel"):
|
||||
for phase in (
|
||||
"foundation",
|
||||
"runtime-reconciliation",
|
||||
"backhaul",
|
||||
"relay",
|
||||
"core-channel",
|
||||
):
|
||||
result = self.build(
|
||||
inbox,
|
||||
phase,
|
||||
@@ -261,6 +273,69 @@ class DeviceEdgeVpsArtifactTest(unittest.TestCase):
|
||||
self.assertIn("command_transport=disabled", rendered)
|
||||
self.assertIn("gelios=untouched", rendered)
|
||||
|
||||
def test_runtime_reconciliation_plan_is_exact_and_opens_no_port(self):
|
||||
with tempfile.TemporaryDirectory(prefix="nodedc-vps-reconcile-plan-") as directory:
|
||||
inbox = Path(directory) / "inbox"
|
||||
inbox.mkdir()
|
||||
result = self.build(
|
||||
inbox,
|
||||
"runtime-reconciliation",
|
||||
"device-edge-vps-runtime-reconciliation-plan-001",
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
artifact = Path(json.loads(result.stdout)["artifact"])
|
||||
old_inbox = RUNNER.INBOX_ROOT
|
||||
RUNNER.INBOX_ROOT = inbox
|
||||
try:
|
||||
with patch.object(RUNNER, "assert_root"), patch.object(
|
||||
RUNNER,
|
||||
"preflight",
|
||||
return_value={
|
||||
"predecessor": (
|
||||
"failed-core-channel-001-rollback-runtime-mode-drift"
|
||||
),
|
||||
},
|
||||
), patch("builtins.print") as output:
|
||||
RUNNER.plan_artifact(str(artifact))
|
||||
finally:
|
||||
RUNNER.INBOX_ROOT = old_inbox
|
||||
rendered = "\n".join(
|
||||
" ".join(str(arg) for arg in call.args)
|
||||
for call in output.call_args_list
|
||||
)
|
||||
self.assertIn("phase=runtime-reconciliation", rendered)
|
||||
self.assertIn(
|
||||
"runtime_reconciliation=exact-known-binaries:0644=>0755",
|
||||
rendered,
|
||||
)
|
||||
self.assertIn("public_core_channel=disabled", rendered)
|
||||
self.assertIn("tracker_tcp_9921=closed", rendered)
|
||||
|
||||
def test_publish_payload_preserves_unselected_executable_modes(self):
|
||||
with tempfile.TemporaryDirectory(prefix="nodedc-vps-publish-scope-") as directory:
|
||||
root = Path(directory)
|
||||
live = root / "live"
|
||||
payload = root / "payload"
|
||||
runtime = live / "runtime/node/bin/node"
|
||||
marker = payload / "deployment/reconciliation.json"
|
||||
runtime.parent.mkdir(parents=True)
|
||||
marker.parent.mkdir(parents=True)
|
||||
runtime.write_bytes(b"runtime-binary")
|
||||
runtime.chmod(0o755)
|
||||
marker.write_text("{}\n", encoding="utf-8")
|
||||
old_live = RUNNER.LIVE_ROOT
|
||||
RUNNER.LIVE_ROOT = live
|
||||
try:
|
||||
with patch.object(RUNNER.os, "chown"):
|
||||
RUNNER.publish_payload(payload, ("deployment/reconciliation.json",))
|
||||
finally:
|
||||
RUNNER.LIVE_ROOT = old_live
|
||||
self.assertEqual(runtime.stat().st_mode & 0o777, 0o755)
|
||||
self.assertEqual(
|
||||
(live / "deployment/reconciliation.json").stat().st_mode & 0o777,
|
||||
0o644,
|
||||
)
|
||||
|
||||
def test_source_baseline_is_pinned_to_the_exact_accepted_predecessor(self):
|
||||
with tempfile.TemporaryDirectory(prefix="nodedc-vps-baseline-") as directory:
|
||||
journal = Path(directory) / "applied.jsonl"
|
||||
|
||||
Reference in New Issue
Block a user