From 35a66f5a8b6c152755b15c1f7d0c1b9b1dedaea7 Mon Sep 17 00:00:00 2001 From: Monika Kairaityte Date: Wed, 4 Jun 2025 11:45:02 +0300 Subject: [PATCH 1/2] Fix relative host path resolution for volume bind mount source e03d675b9bcd92864fd1aedc23d92f72e410a54d broke relative host path resolution by deleting os.chdir(). After this commit current working directory is not relevant anymore. Fixes e03d675b9bcd92864fd1aedc23d92f72e410a54d. Signed-off-by: Monika Kairaityte --- podman_compose.py | 1 + .../selinux/test_podman_compose_selinux.py | 10 ++- tests/unit/test_container_to_args.py | 78 ++++++++++++++++++- 3 files changed, 81 insertions(+), 8 deletions(-) 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"), From 32b3d26ab1787c3153baae6c9d713a4382655c3c Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Thu, 5 Jun 2025 17:00:21 +0300 Subject: [PATCH 2/2] Add newsfragment Signed-off-by: Povilas Kanapickas --- newsfragments/relative-host-path-resolution-bind-volume.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 newsfragments/relative-host-path-resolution-bind-volume.bugfix 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