diff --git a/newsfragments/relative-host-path-resolution-bind-volume.bugfix b/newsfragments/relative-host-path-resolution-bind-volume.bugfix new file mode 100644 index 0000000..0bee858 --- /dev/null +++ b/newsfragments/relative-host-path-resolution-bind-volume.bugfix @@ -0,0 +1 @@ +Fixed relative host path resolution for volume bind mount source diff --git a/podman_compose.py b/podman_compose.py index ffbc1ae..c01b80c 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -395,6 +395,7 @@ async def assert_volume(compose, mount_dict): os.makedirs(mount_src, exist_ok=True) except OSError: pass + mount_dict["source"] = mount_src return if mount_dict["type"] != "volume" or not vol or not vol.get("name"): return diff --git a/tests/integration/selinux/test_podman_compose_selinux.py b/tests/integration/selinux/test_podman_compose_selinux.py index 2c04d18..24db7f4 100644 --- a/tests/integration/selinux/test_podman_compose_selinux.py +++ b/tests/integration/selinux/test_podman_compose_selinux.py @@ -36,8 +36,9 @@ class TestPodmanCompose(unittest.TestCase, RunSubprocessMixin): "selinux_container1_1", ]) inspect_out = json.loads(out) - create_command_list = inspect_out[0].get("Config", []).get("CreateCommand", {}) - self.assertIn('./host_test_text.txt:/test_text.txt:z', create_command_list) + create_command_list = inspect_out[0].get("Config", []).get("CreateCommand", []) + host_path = os.path.join(test_path(), "selinux", "host_test_text.txt") + self.assertIn(f'{host_path}:/test_text.txt:z', create_command_list) out, _ = self.run_subprocess_assert_returncode([ "podman", @@ -45,8 +46,9 @@ class TestPodmanCompose(unittest.TestCase, RunSubprocessMixin): "selinux_container2_1", ]) inspect_out = json.loads(out) - create_command_list = inspect_out[0].get("Config", []).get("CreateCommand", {}) - self.assertIn('./host_test_text.txt:/test_text.txt', create_command_list) + create_command_list = inspect_out[0].get("Config", []).get("CreateCommand", []) + host_path = os.path.join(test_path(), "selinux", "host_test_text.txt") + self.assertIn(f'{host_path}:/test_text.txt', create_command_list) finally: out, _ = self.run_subprocess_assert_returncode([ podman_compose_path(), diff --git a/tests/unit/test_container_to_args.py b/tests/unit/test_container_to_args.py index ee07b92..acf6195 100644 --- a/tests/unit/test_container_to_args.py +++ b/tests/unit/test_container_to_args.py @@ -529,10 +529,24 @@ class TestContainerToArgs(unittest.IsolatedAsyncioTestCase): ) @parameterized.expand([ - (False, "z", ["--mount", "type=bind,source=./foo,destination=/mnt,z"]), - (False, "Z", ["--mount", "type=bind,source=./foo,destination=/mnt,Z"]), - (True, "z", ["-v", "./foo:/mnt:z"]), - (True, "Z", ["-v", "./foo:/mnt:Z"]), + ( + False, + "z", + [ + "--mount", + f"type=bind,source={get_test_file_path('test_dirname/foo')},destination=/mnt,z", + ], + ), + ( + False, + "Z", + [ + "--mount", + f"type=bind,source={get_test_file_path('test_dirname/foo')},destination=/mnt,Z", + ], + ), + (True, "z", ["-v", f"{get_test_file_path('test_dirname/foo')}:/mnt:z"]), + (True, "Z", ["-v", f"{get_test_file_path('test_dirname/foo')}:/mnt:Z"]), ]) async def test_selinux_volume(self, prefer_volume, selinux_type, expected_additional_args): c = create_compose_mock() @@ -567,6 +581,62 @@ class TestContainerToArgs(unittest.IsolatedAsyncioTestCase): ], ) + @parameterized.expand([ + ( + "absolute_path", + get_test_file_path('test_dirname/foo'), + [ + "--mount", + f"type=bind,source={get_test_file_path('test_dirname/foo')},destination=/mnt", + ], + ), + ( + "relative_path", + './foo', + [ + "--mount", + f"type=bind,source={get_test_file_path('test_dirname/foo')},destination=/mnt", + ], + ), + ( + "home_dir", + '~/test_dirname/foo', + [ + "--mount", + f"type=bind,source={os.path.expanduser('~/test_dirname/foo')},destination=/mnt", + ], + ), + ]) + async def test_volumes_bind_mount_source( + 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": "bind", + "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([ ("not_compat", False, "test_project_name", "test_project_name_network1"), ("compat_no_dash", True, "test_project_name", "test_project_name_network1"),