Restrict launches to prepared runtimes (Refs #93)
CI / checks (push) Successful in 4m53s

This commit is contained in:
2026-10-09 17:15:15 -04:00
parent f0afd6de67
commit 596b160be3
36 changed files with 347 additions and 116 deletions
+52 -2
View File
@@ -2502,12 +2502,62 @@ class AgentTests(unittest.TestCase):
return f"ghcr.io/ayymoss/plutainer|latest|{image_digest}|{image_id}\n"
return original(*args, **kwargs)
self.docker.call = call
module.atomic_json(self.agent.root / "agent/runtime-images.json", {"ghcr.io/ayymoss/plutainer": image_id, "removed-image": "missing-id"})
images = self.agent.inventory()["runtimeImages"]
prepared = ["ghcr.io/ayymoss/plutainer", "ghcr.io/ayymoss/plutainer@" + image_digest]
module.atomic_json(self.agent.root / "agent/runtime-images.json", {**dict.fromkeys(prepared, image_id), "removed-image": "missing-id"})
inventory = self.agent.inventory()
images = inventory["runtimeImages"]
self.assertIn("ghcr.io/ayymoss/plutainer@" + image_digest, images)
self.assertIn("ghcr.io/ayymoss/plutainer:latest", images)
self.assertIn("ghcr.io/ayymoss/plutainer", images)
self.assertNotIn("removed-image", images)
self.assertEqual(inventory["preparedRuntimeImages"], prepared)
def test_runtime_pull_prepares_only_the_requested_reference_from_the_docker_cache(self):
image = "registry.example/custom-runtime:stable"
image_id = "sha256:" + "1" * 64
original = self.docker.call
def call(*args, **kwargs):
if args[:2] == ("image", "ls"):
return (f"registry.example/custom-runtime|stable|<none>|{image_id}\n"
f"registry.example/custom-runtime|unprepared-alias|<none>|{image_id}\n"
"unrelated-service|latest|<none>|sha256:unrelated\n")
if args[:2] == ("image", "inspect"):
self.assertEqual(args[-1], image)
return image_id
return original(*args, **kwargs)
self.docker.call = call
before = self.agent.inventory()
self.assertIn(image, before["runtimeImages"])
self.assertIn("unrelated-service:latest", before["runtimeImages"])
self.assertEqual(before["preparedRuntimeImages"], [])
result = self.agent.execute(self.operation("runtime.pull", {"image": image}))
self.assertEqual(result["state"], "completed")
inventory = self.agent.inventory()
self.assertEqual(inventory["runtimeImages"], before["runtimeImages"])
self.assertEqual(inventory["preparedRuntimeImages"], [image])
def test_runtime_preparation_inventory_fails_closed_when_records_or_docker_are_unavailable(self):
aliases = self.agent.root / "agent/runtime-images.json"
original = self.docker.call
def call(*args, **kwargs):
if args[:2] == ("image", "ls"):
return "custom-runtime|latest|<none>|sha256:prepared\n"
return original(*args, **kwargs)
self.docker.call = call
for content in ("invalid json", "[]", '{"custom-runtime:latest": []}', '{"custom-runtime:latest": "sha256:removed"}'):
with self.subTest(content=content):
aliases.write_text(content)
inventory = self.agent.inventory()
self.assertEqual(inventory["preparedRuntimeImages"], [])
self.assertEqual(inventory["runtimeImages"], ["custom-runtime:latest"])
module.atomic_json(aliases, {"custom-runtime:latest": "sha256:prepared"})
with patch.object(self.docker, "call", side_effect=AgentError("Docker unavailable")):
self.assertEqual(self.agent.inventory()["preparedRuntimeImages"], [])
def test_heartbeat_applies_configured_host_port_range_before_deployment(self):
self.agent.request = lambda *_: {"host": {"portMin": 30000, "portMax": 30100}}