diff --git a/docs/Extensions.md b/docs/Extensions.md index 4626a307..1f422d5a 100644 --- a/docs/Extensions.md +++ b/docs/Extensions.md @@ -151,6 +151,17 @@ In addition, podman-compose supports the following podman-specific values for `n The options to the network modes are passed to the `--network` option of the `podman create` command as-is. +## Podman-specific mount types + +Generic docker-compose supports the following values for mount `type`: + +- `volume` +- `bind` +- `tmpfs` + +In addition, podman-compose supports the following podman-pecific values for mount `type`: + +- `glob` ## Docker Compose Compatibility @@ -270,4 +281,4 @@ When not set in docker-compose.yml or on the command line, the pod args default to `["--infra=false", "--share="]`. This setting can also be changed by setting `PODMAN_COMPOSE_POD_ARGS` environment -variable. \ No newline at end of file +variable. diff --git a/newsfragments/allow-glob-volume-definition.feature b/newsfragments/allow-glob-volume-definition.feature new file mode 100644 index 00000000..e2a5c68a --- /dev/null +++ b/newsfragments/allow-glob-volume-definition.feature @@ -0,0 +1 @@ +Support usage of 'glob' mount type when defining volumes. diff --git a/podman_compose.py b/podman_compose.py index 46725ffd..7649e331 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -483,6 +483,8 @@ def mount_desc_to_mount_args(mount_desc: dict[str, Any]) -> str: opts_str = ",".join(opts) if mount_type == "bind": return f"type=bind,source={source},destination={target},{opts_str}".rstrip(",") + if mount_type == "glob": + return f"type=glob,source={source},destination={target},{opts_str}".rstrip(",") if mount_type == "volume": return f"type=volume,source={source},destination={target},{opts_str}".rstrip(",") if mount_type == "tmpfs": @@ -519,7 +521,7 @@ def container_to_ulimit_build_args(cnt: dict[str, Any], podman_args: list[str]) def mount_desc_to_volume_args(mount_desc: dict[str, Any], srv_name: str) -> str: mount_type = mount_desc["type"] - if mount_type not in ("bind", "volume"): + if mount_type not in ("bind", "volume", "glob"): raise ValueError("unknown mount type:" + mount_type) vol = mount_desc.get("_vol") if mount_type == "volume" else None source = vol["name"] if vol else mount_desc.get("source") @@ -574,7 +576,8 @@ async def get_mount_args( srv_name = cnt["_service"] mount_type = volume["type"] await assert_volume(compose, volume) - if compose.prefer_volume_over_mount: + # 'glob' mount type requires usage of '--mount', despite preference + if mount_type != "glob" and compose.prefer_volume_over_mount: if mount_type == "tmpfs": # TODO: --tmpfs /tmp:rw,size=787448k,mode=1777 args = volume["target"] diff --git a/tests/unit/test_container_to_args.py b/tests/unit/test_container_to_args.py index 3d035ae4..40e5a028 100644 --- a/tests/unit/test_container_to_args.py +++ b/tests/unit/test_container_to_args.py @@ -624,6 +624,50 @@ async def test_selinux_volume( ], ) + @parameterized.expand([ + ( + "glob_mount", + get_test_file_path('test_dirname/foo') + "/*.ext", + [ + "--mount", + ( + "type=glob,source=" + f"{get_test_file_path('test_dirname/foo') + '/*.ext'}," + "destination=/mnt" + ), + ], + ), + ]) + async def test_volumes_glob_mount_soure( # pylint: disable=unused-argument + self, test_name: str, mount_source: str, expected_additional_args: list + ) -> None: + c = create_compose_mock() + cnt = get_minimal_container() + + # This is supposed to happen during `_parse_compose_file` + # but that is probably getting skipped during testing + cnt["_service"] = cnt["service_name"] + + cnt["volumes"] = [ + { + "type": "glob", + "source": f"{mount_source}", + "target": "/mnt", + } + ] + + args = await container_to_args(c, cnt) + self.assertEqual( + args, + [ + "--name=project_name_service_name1", + "-d", + *expected_additional_args, + "--network=bridge:alias=service_name", + "busybox", + ], + ) + @parameterized.expand([ ( "absolute_path",