diff --git a/podman_compose.py b/podman_compose.py index 46725ffd..a24aa612 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -63,6 +63,8 @@ def filteri(a: list[str]) -> list[str]: @overload def try_int(i: int | str, fallback: int) -> int: ... + + @overload def try_int(i: int | str, fallback: None) -> int | None: ... @@ -272,8 +274,12 @@ def fix_mount_dict( @overload def rec_subs(value: dict, subs_dict: dict[str, Any]) -> dict: ... + + @overload def rec_subs(value: str, subs_dict: dict[str, Any]) -> str: ... + + @overload def rec_subs(value: Iterable, subs_dict: dict[str, Any]) -> Iterable: ... @@ -2376,7 +2382,18 @@ def _parse_compose_file(self) -> None: # If `include` is used, append included files to files include = compose.get("include") if include: - files.extend([os.path.join(os.path.dirname(filename), i) for i in include]) + # Check if 'include' block is dict or list of strings + for i in include: + if isinstance(i, str): + files.append(os.path.join(os.path.dirname(filename), i)) + elif isinstance(i, dict): + path = i.get("path") + if path: + # Extend files list with values from path key + files.extend([os.path.join(os.path.dirname(filename), p) for p in path]) + elif not path: + # Raise error if path is missing + raise RuntimeError("Please use 'path' as key in include block") # As compose obj is updated and tested with every loop, not deleting `include` # from it, results in it being tested again and again, original values for # `include` be appended to `files`, and, included files be processed for ever. diff --git a/tests/integration/include/docker-compose.include-dict.yaml b/tests/integration/include/docker-compose.include-dict.yaml new file mode 100644 index 00000000..40826190 --- /dev/null +++ b/tests/integration/include/docker-compose.include-dict.yaml @@ -0,0 +1,6 @@ +version: '3.6' + +include: + - path: + - docker-compose.base.yaml + - docker-compose.extend.yaml diff --git a/tests/integration/include/test_podman_compose_include.py b/tests/integration/include/test_podman_compose_include.py index bdd1857e..f8d1731e 100644 --- a/tests/integration/include/test_podman_compose_include.py +++ b/tests/integration/include/test_podman_compose_include.py @@ -62,3 +62,63 @@ def test_podman_compose_include(self) -> None: # check container did not exists anymore out, _ = self.run_subprocess_assert_returncode(command_check_container) self.assertEqual(out, b"") + + def test_podman_compose_include_dict(self) -> None: + """ + Test that podman-compose can execute podman-compose -f up with include + :return: + """ + main_path = Path(__file__).parent.parent.parent.parent + + command_up = [ + "coverage", + "run", + str(main_path.joinpath("podman_compose.py")), + "-f", + str( + main_path.joinpath( + "tests", "integration", "include", "docker-compose.include-dict.yaml" + ) + ), + "up", + "-d", + ] + + command_check_container = [ + "podman", + "ps", + "-a", + "--filter", + "label=io.podman.compose.project=include", + "--format", + '"{{.Image}}"', + ] + + command_container_id = [ + "podman", + "ps", + "-a", + "--filter", + "label=io.podman.compose.project=include", + "--format", + '"{{.ID}}"', + ] + + command_down = ["podman", "rm", "--force"] + + self.run_subprocess_assert_returncode(command_up) + out, _ = self.run_subprocess_assert_returncode(command_check_container) + expected_output = b'"localhost/nopush/podman-compose-test:latest"\n' * 2 + self.assertEqual(out, expected_output) + # Get container ID to remove it + out, _ = self.run_subprocess_assert_returncode(command_container_id) + self.assertNotEqual(out, b"") + container_ids = out.decode().strip().split("\n") + container_ids = [container_id.replace('"', "") for container_id in container_ids] + command_down.extend(container_ids) + out, _ = self.run_subprocess_assert_returncode(command_down) + # cleanup test image(tags) + self.assertNotEqual(out, b"") + # check container did not exists anymore + out, _ = self.run_subprocess_assert_returncode(command_check_container) + self.assertEqual(out, b"")