diff --git a/src/agent_env/bundle/importer.py b/src/agent_env/bundle/importer.py index e5d1e776..731c9c18 100644 --- a/src/agent_env/bundle/importer.py +++ b/src/agent_env/bundle/importer.py @@ -93,7 +93,8 @@ def task_images(task_id: str, *, version: int | None = None, include_scopes: Collection[FieldScope] = ()) -> tuple[DockerImageArtifact, ...]: """The images ``import_task`` writes for the stored task ``task_id``, at ``version`` or its latest, each once in the order it reaches them, found without downloading anything: what an export pushes to a registry before importing the - task with ``image_refs`` naming them there. Raises BundleError when the import would fail on what it reads.""" + task with ``image_refs`` naming them there. Every image is listed, however it's stored, since each is then given a + reference; raises BundleError when the import would fail on anything else it reads.""" importer = _Importer(None, include_scopes) importer.add_task(Task.get(task_id, version)) if importer.problems: @@ -284,6 +285,8 @@ def image(self, out: _EntityOut, artifact: DockerImageArtifact, key: str) -> str registry ref, else a pinned store image. Given a registry reference for it, that reference, its tag pinned to the digest the registry serves now when it gives none, with the context kept beside it when it has one.""" self.images_named.setdefault((artifact.id, artifact.version), artifact) + if self.dest is None: # only listed, never written: each image is given a reference before an import is + return {"ref": artifact.image_name} ref = self.image_refs.get(artifact.id) if ref is not None: self.refs_used.add(artifact.id) diff --git a/tst/unit/bundle/importer_image_refs_test.py b/tst/unit/bundle/importer_image_refs_test.py index b4c5b0ac..a55758a4 100644 --- a/tst/unit/bundle/importer_image_refs_test.py +++ b/tst/unit/bundle/importer_image_refs_test.py @@ -212,11 +212,21 @@ def test_the_images_a_task_writes_are_listed_once_in_order_without_downloading_a refs["crm-image"], refs["crm-image"], refs["mail-image"]] -def test_listing_a_task_the_import_cant_write_fails_before_any_push_would_start(home): +def test_an_image_the_import_writes_only_with_a_ref_is_listed_and_takes_one(home): + """A tarball under a bare name is what an export loads and pushes, so it's listed, not refused.""" _stored(get_artifact_store().put_document(DockerImageArtifact( id="crm-image", description="d", image_name="crm-image:v1", tar_gz_s3_url="file:///nowhere/crm.tar.gz"))) + (image,) = task_images("t") + imported = import_task("t", home / "t", image_refs={image.id: REF}) + + assert (image.id, _toml(imported.root, "envs/crm/env.toml")["image"]) == ("crm-image", {"ref": REF}) + + +def test_listing_a_task_the_import_cant_write_fails_before_any_push_would_start(home): + Task.put(id="t", steps=[build_step(dict(DEPLOY))]) # its env isn't in the store + with pytest.raises(BundleError) as caught: task_images("t") - assert any("stored only as a docker save tarball" in problem for problem in caught.value.problems) + assert any("crm" in problem for problem in caught.value.problems)