Skip to content

Commit b3c6635

Browse files
authored
Merge pull request #1348 from fccagou/feat-process-subpath-in-volume-type
Add subpath support to volumes with type volume in `--mount`
2 parents 7986123 + ee52293 commit b3c6635

File tree

2 files changed

+58
-7
lines changed

2 files changed

+58
-7
lines changed

podman_compose.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,8 @@ async def assert_volume(compose: PodmanCompose, mount_dict: dict[str, Any]) -> N
428428
# podman volume list --format '{{.Name}}\t{{.MountPoint}}' \
429429
# -f 'label=io.podman.compose.project=HERE'
430430
try:
431-
_ = (await compose.podman.output([], "volume", ["inspect", vol_name])).decode("utf-8")
431+
await compose.podman.output([], "volume", ["inspect", vol_name])
432+
432433
except subprocess.CalledProcessError as e:
433434
if is_ext:
434435
raise RuntimeError(f"External volume [{vol_name}] does not exist") from e
@@ -450,7 +451,7 @@ async def assert_volume(compose: PodmanCompose, mount_dict: dict[str, Any]) -> N
450451
args.extend(["--opt", f"{opt}={value}"])
451452
args.append(vol_name)
452453
await compose.podman.output([], "volume", args)
453-
_ = (await compose.podman.output([], "volume", ["inspect", vol_name])).decode("utf-8")
454+
await compose.podman.output([], "volume", ["inspect", vol_name])
454455

455456

456457
def mount_desc_to_mount_args(mount_desc: dict[str, Any]) -> str:
@@ -480,11 +481,14 @@ def mount_desc_to_mount_args(mount_desc: dict[str, Any]) -> str:
480481
selinux = bind_opts.get("selinux")
481482
if selinux is not None:
482483
opts.append(selinux)
483-
if mount_type == "image":
484-
image_opts = mount_desc.get("image", {})
485-
subpath = image_opts.get("subpath")
484+
485+
# According to compose specifications https://docs.docker.com/reference/compose-file/services/#volumes
486+
# subpath can be used in image and volume mount type
487+
if mount_type in ["volume", "image"] and mount_desc.get(mount_type):
488+
subpath = mount_desc.get(mount_type, {}).get("subpath")
486489
if subpath is not None:
487490
opts.append(f"subpath={subpath}")
491+
488492
opts_str = ",".join(opts)
489493
if mount_type == "bind":
490494
return f"type=bind,source={source},destination={target},{opts_str}".rstrip(",")
@@ -582,9 +586,13 @@ async def get_mount_args(
582586
volume = get_mnt_dict(compose, cnt, volume)
583587
srv_name = cnt["_service"]
584588
mount_type = volume["type"]
585-
ignore_mount_type = {"image", "glob"}
589+
# By default, mount using -v is actually preferred over --mount.
590+
# In some case, options can only be set using --mount.
591+
# --mount is forced for type set in mount_over_volume_needed var.
592+
#
593+
mount_over_volume_needed = {"image", "glob", "volume"}
586594
await assert_volume(compose, volume)
587-
if compose.prefer_volume_over_mount and mount_type not in ignore_mount_type:
595+
if compose.prefer_volume_over_mount and mount_type not in mount_over_volume_needed:
588596
if mount_type == "tmpfs":
589597
# TODO: --tmpfs /tmp:rw,size=787448k,mode=1777
590598
args = volume["target"]

tests/unit/test_container_to_args.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,49 @@ async def test_volumes_image_mount(
756756
],
757757
)
758758

759+
@parameterized.expand([
760+
(
761+
"without_subpath",
762+
{},
763+
"type=volume,source=volname,destination=/mnt/example",
764+
),
765+
(
766+
"with_subpath",
767+
{"volume": {"subpath": "path/to/image/folder"}},
768+
"type=volume,source=volname,destination=/mnt/example,subpath=path/to/image/folder",
769+
),
770+
])
771+
async def test_volumes_mount(
772+
self, test_name: str, volume_opts: dict, expected_mount_arg: str
773+
) -> None:
774+
c = create_compose_mock()
775+
c.vols = {"volname": {"name": "volname"}}
776+
777+
cnt = get_minimal_container()
778+
cnt["_service"] = cnt["service_name"]
779+
780+
cnt["volumes"] = [
781+
{
782+
"type": "volume",
783+
"source": "volname",
784+
"target": "/mnt/example",
785+
**volume_opts,
786+
},
787+
]
788+
789+
args = await container_to_args(c, cnt)
790+
self.assertEqual(
791+
args,
792+
[
793+
"--name=project_name_service_name1",
794+
"-d",
795+
"--mount",
796+
expected_mount_arg,
797+
"--network=bridge:alias=service_name",
798+
"busybox",
799+
],
800+
)
801+
759802
@parameterized.expand([
760803
(
761804
"create_host_path_set_to_true",

0 commit comments

Comments
 (0)