Skip to content

Commit a086cbf

Browse files
committed
Implement 'image' volume type for services
This adds support for volume.type=image in services, as specified in [Compose spec](https://github.com/compose-spec/compose-spec/blob/76d4a3d08f9d4eb251092746394a64327031a6c6/05-services.md#long-syntax-5). Fixes #1202 Signed-off-by: Atte Lautanala <[email protected]>
1 parent a1f3bef commit a086cbf

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support volume.type=image in services, for mounting files from container images.

podman_compose.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,13 +480,20 @@ def mount_desc_to_mount_args(mount_desc: dict[str, Any]) -> str:
480480
selinux = bind_opts.get("selinux")
481481
if selinux is not None:
482482
opts.append(selinux)
483+
if mount_type == "image":
484+
image_opts = mount_desc.get("image", {})
485+
subpath = image_opts.get("subpath")
486+
if subpath is not None:
487+
opts.append(f"subpath={subpath}")
483488
opts_str = ",".join(opts)
484489
if mount_type == "bind":
485490
return f"type=bind,source={source},destination={target},{opts_str}".rstrip(",")
486491
if mount_type == "volume":
487492
return f"type=volume,source={source},destination={target},{opts_str}".rstrip(",")
488493
if mount_type == "tmpfs":
489494
return f"type=tmpfs,destination={target},{opts_str}".rstrip(",")
495+
if mount_type == "image":
496+
return f"type=image,source={source},destination={target},{opts_str}".rstrip(",")
490497
raise ValueError("unknown mount type:" + mount_type)
491498

492499

@@ -574,7 +581,7 @@ async def get_mount_args(
574581
srv_name = cnt["_service"]
575582
mount_type = volume["type"]
576583
await assert_volume(compose, volume)
577-
if compose.prefer_volume_over_mount:
584+
if compose.prefer_volume_over_mount and mount_type != "image":
578585
if mount_type == "tmpfs":
579586
# TODO: --tmpfs /tmp:rw,size=787448k,mode=1777
580587
args = volume["target"]

tests/unit/test_container_to_args.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,47 @@ async def test_volumes_bind_mount_source(
680680
],
681681
)
682682

683+
@parameterized.expand([
684+
(
685+
"without_subpath",
686+
{},
687+
"type=image,source=example:latest,destination=/mnt/example",
688+
),
689+
(
690+
"with_subpath",
691+
{"image": {"subpath": "path/to/image/folder"}},
692+
"type=image,source=example:latest,destination=/mnt/example,subpath=path/to/image/folder",
693+
)
694+
])
695+
async def test_volumes_image_mount(
696+
self, test_name: str, image_opts: dict, expected_mount_arg: str
697+
) -> None:
698+
c = create_compose_mock()
699+
cnt = get_minimal_container()
700+
cnt["_service"] = cnt["service_name"]
701+
702+
cnt["volumes"] = [
703+
{
704+
"type": "image",
705+
"source": "example:latest",
706+
"target": "/mnt/example",
707+
**image_opts,
708+
},
709+
]
710+
711+
args = await container_to_args(c, cnt)
712+
self.assertEqual(
713+
args,
714+
[
715+
"--name=project_name_service_name1",
716+
"-d",
717+
"--mount",
718+
expected_mount_arg,
719+
"--network=bridge:alias=service_name",
720+
"busybox",
721+
],
722+
)
723+
683724
@parameterized.expand([
684725
(
685726
"create_host_path_set_to_true",

0 commit comments

Comments
 (0)