Restrict launches to prepared runtime images
This commit is contained in:
+4
-2
@@ -32,7 +32,7 @@ import urllib.parse
|
||||
import urllib.request
|
||||
import uuid
|
||||
|
||||
VERSION = "1.5.0"
|
||||
VERSION = "1.5.1"
|
||||
LABEL = "io.electric-cherry"
|
||||
MAX_FILE = 32 * 1024 * 1024
|
||||
MANIFEST_MAX_ENTRIES = 10000
|
||||
@@ -1505,7 +1505,9 @@ class Agent:
|
||||
atomic_bytes(env_path, "".join(f"{key}={value}\n" for key, value in env.items()).encode())
|
||||
name = self.container_name(instance_id, generation)
|
||||
spec_sha = digest(json.dumps(payload, sort_keys=True, separators=(",", ":")).encode())
|
||||
args = ["container", "create", "--name", name, "--restart", "unless-stopped", "--label", LABEL + ".managed=true", "--label", LABEL + ".instance=" + instance_id, "--label", LABEL + ".generation=" + str(generation), "--label", LABEL + ".operation=" + (self.executing_id or "direct"), "--label", LABEL + ".spec-sha256=" + spec_sha, "--mount", f"type=bind,src={app},dst=/home/plutainer/app", "--mount", f"type=bind,src={library / 'content'},dst=/home/plutainer/gamefiles,readonly", "--env-file", str(env_path)]
|
||||
# Do not let Docker fetch a replacement if the prepared image disappears
|
||||
# between validation and container creation.
|
||||
args = ["container", "create", "--pull=never", "--name", name, "--restart", "unless-stopped", "--label", LABEL + ".managed=true", "--label", LABEL + ".instance=" + instance_id, "--label", LABEL + ".generation=" + str(generation), "--label", LABEL + ".operation=" + (self.executing_id or "direct"), "--label", LABEL + ".spec-sha256=" + spec_sha, "--mount", f"type=bind,src={app},dst=/home/plutainer/app", "--mount", f"type=bind,src={library / 'content'},dst=/home/plutainer/gamefiles,readonly", "--env-file", str(env_path)]
|
||||
if self.config.get("hostId"):
|
||||
args.extend(["--label", LABEL + ".host=" + identifier(self.config["hostId"])])
|
||||
bind_arg = "[" + bind + "]" if ":" in bind else bind
|
||||
|
||||
@@ -727,6 +727,29 @@ class AgentTests(unittest.TestCase):
|
||||
self.assertEqual(second["result"], first["result"])
|
||||
self.assertEqual(sum(call[:2] == ("container", "restart") for call in self.docker.calls), 1)
|
||||
|
||||
def test_creation_uses_cached_runtime_without_allowing_docker_to_pull(self):
|
||||
payload = self.create()
|
||||
creation = next(args for args in self.docker.calls if args[:2] == ("container", "create"))
|
||||
self.assertIn("--pull=never", creation)
|
||||
self.assertEqual(creation[-1], payload["image"])
|
||||
self.assertFalse(any(args[:2] == ("image", "pull") for args in self.docker.calls))
|
||||
|
||||
def test_image_disappearing_after_validation_cannot_be_pulled_or_started(self):
|
||||
original = self.docker.call
|
||||
|
||||
def missing_image(*args, **kwargs):
|
||||
if args[:2] == ("container", "create"):
|
||||
self.assertIn("--pull=never", args)
|
||||
raise AgentError("No such image")
|
||||
return original(*args, **kwargs)
|
||||
|
||||
payload = {"game": "t5", "libraryId": self.library_id, "image": "prepared:runtime", "port": 28960}
|
||||
with patch.object(self.docker, "call", side_effect=missing_image):
|
||||
with self.assertRaisesRegex(AgentError, "No such image"):
|
||||
self.agent.create(INSTANCE, 1, payload)
|
||||
self.assertEqual(self.docker.started, 0)
|
||||
self.assertFalse(any(args[:2] == ("image", "pull") for args in self.docker.calls))
|
||||
|
||||
def test_manifest_is_advertised_and_reconciles_as_a_read_operation(self):
|
||||
self.create()
|
||||
operation = self.operation("files.manifest", {"roots": ["configs", "scripts"], "ignoreNames": [], "paths": ["configs/server.cfg"]})
|
||||
|
||||
Reference in New Issue
Block a user