From cbe95879731c4763e5a605e9cff5b47f245e377b Mon Sep 17 00:00:00 2001 From: Sebastian Sellmeier Date: Thu, 1 Feb 2024 09:41:45 +0100 Subject: [PATCH 1/6] Implement override and reset analog to docker-compose Corresponding Docker compose file documentation: https://docs.docker.com/reference/compose-file/merge/ Signed-off-by: Sebastian Sellmeier Co-authored-by: Monika Kairaityte --- ...implement-merge-reset-and-override.feature | 1 + podman_compose.py | 96 ++++++++++++++++++- 2 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 newsfragments/implement-merge-reset-and-override.feature diff --git a/newsfragments/implement-merge-reset-and-override.feature b/newsfragments/implement-merge-reset-and-override.feature new file mode 100644 index 0000000..b173272 --- /dev/null +++ b/newsfragments/implement-merge-reset-and-override.feature @@ -0,0 +1 @@ +- Add support for `reset` and `override` tags to be used when merging several compose files. diff --git a/podman_compose.py b/podman_compose.py index 5a5e18b..4808dd9 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -1407,6 +1407,57 @@ def flat_deps(services, with_extends=False): rec_deps(services, name) +################### +# Override and reset tags +################### + + +class OverrideTag(yaml.YAMLObject): + yaml_dumper = yaml.Dumper + yaml_loader = yaml.SafeLoader + yaml_tag = '!override' + + def __init__(self, value): + if len(value) > 0 and isinstance(value[0], tuple): + self.value = {} + # item is a tuple representing service's lower level key and value + for item in value: + # value can actually be a list, then all the elements from the list have to be + # collected + if isinstance(item[1].value, list): + self.value[item[0].value] = [item.value for item in item[1].value] + else: + self.value[item[0].value] = item[1].value + else: + self.value = [item.value for item in value] + + @classmethod + def from_yaml(cls, loader, node): + return OverrideTag(node.value) + + @classmethod + def to_yaml(cls, dumper, data): + return dumper.represent_scalar(cls.yaml_tag, data.value) + + +class ResetTag(yaml.YAMLObject): + yaml_dumper = yaml.Dumper + yaml_loader = yaml.SafeLoader + yaml_tag = '!reset' + + @classmethod + def to_json(cls): + return cls.yaml_tag + + @classmethod + def from_yaml(cls, loader, node): + return ResetTag() + + @classmethod + def to_yaml(cls, dumper, data): + return dumper.represent_scalar(cls.yaml_tag, '') + + async def wait_with_timeout(coro, timeout): """ Asynchronously waits for the given coroutine to complete with a timeout. @@ -1605,6 +1656,12 @@ class Podman: def normalize_service(service, sub_dir=""): + if isinstance(service, ResetTag): + return service + + if isinstance(service, OverrideTag): + service = service.value + if "build" in service: build = service["build"] if isinstance(build, str): @@ -1708,6 +1765,8 @@ def rec_merge_one(target, source): update target from source recursively """ done = set() + remove = set() + for key, value in source.items(): if key in target: continue @@ -1717,15 +1776,37 @@ def rec_merge_one(target, source): if key in done: continue if key not in source: + if isinstance(value, ResetTag): + log("INFO: Unneeded !reset found for [{key}]") + remove.add(key) + + if isinstance(value, OverrideTag): + log("INFO: Unneeded !override found for [{key}] with value '{value}'") + target[key] = clone(value.value) + continue + value2 = source[key] + + if isinstance(value, ResetTag) or isinstance(value2, ResetTag): + remove.add(key) + continue + + if isinstance(value, OverrideTag) or isinstance(value2, OverrideTag): + target[key] = ( + clone(value.value) if isinstance(value, OverrideTag) else clone(value2.value) + ) + continue + if key in ("command", "entrypoint"): target[key] = clone(value2) continue + if not isinstance(value2, type(value)): value_type = type(value) value2_type = type(value2) raise ValueError(f"can't merge value of [{key}] of type {value_type} and {value2_type}") + if is_list(value2): if key == "volumes": # clean duplicate mount targets @@ -1742,6 +1823,10 @@ def rec_merge_one(target, source): rec_merge_one(value, value2) else: target[key] = value2 + + for key in remove: + del target[key] + return target @@ -2027,10 +2112,13 @@ class PodmanCompose: content = rec_subs(content, self.environ) if isinstance(services := content.get('services'), dict): for service in services.values(): - if 'extends' in service and (service_file := service['extends'].get('file')): - service['extends']['file'] = os.path.join( - os.path.dirname(filename), service_file - ) + if not isinstance(service, OverrideTag) and not isinstance(service, ResetTag): + if 'extends' in service and ( + service_file := service['extends'].get('file') + ): + service['extends']['file'] = os.path.join( + os.path.dirname(filename), service_file + ) rec_merge(compose, content) # If `include` is used, append included files to files From 38a9263424c2fc734432be460dc3394cb6d86c1b Mon Sep 17 00:00:00 2001 From: Monika Kairaityte Date: Wed, 30 Apr 2025 19:25:22 +0300 Subject: [PATCH 2/6] integration/tests: Move 'volumes_merge' tests to 'merge' directory Signed-off-by: Monika Kairaityte --- tests/integration/{ => merge}/volumes_merge/__init__.py | 0 .../{ => merge}/volumes_merge/docker-compose.override.yaml | 0 tests/integration/{ => merge}/volumes_merge/docker-compose.yaml | 0 tests/integration/{ => merge}/volumes_merge/index.txt | 0 tests/integration/{ => merge}/volumes_merge/override.txt | 0 .../volumes_merge/test_podman_compose_volumes_merge.py | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename tests/integration/{ => merge}/volumes_merge/__init__.py (100%) rename tests/integration/{ => merge}/volumes_merge/docker-compose.override.yaml (100%) rename tests/integration/{ => merge}/volumes_merge/docker-compose.yaml (100%) rename tests/integration/{ => merge}/volumes_merge/index.txt (100%) rename tests/integration/{ => merge}/volumes_merge/override.txt (100%) rename tests/integration/{ => merge}/volumes_merge/test_podman_compose_volumes_merge.py (100%) diff --git a/tests/integration/volumes_merge/__init__.py b/tests/integration/merge/volumes_merge/__init__.py similarity index 100% rename from tests/integration/volumes_merge/__init__.py rename to tests/integration/merge/volumes_merge/__init__.py diff --git a/tests/integration/volumes_merge/docker-compose.override.yaml b/tests/integration/merge/volumes_merge/docker-compose.override.yaml similarity index 100% rename from tests/integration/volumes_merge/docker-compose.override.yaml rename to tests/integration/merge/volumes_merge/docker-compose.override.yaml diff --git a/tests/integration/volumes_merge/docker-compose.yaml b/tests/integration/merge/volumes_merge/docker-compose.yaml similarity index 100% rename from tests/integration/volumes_merge/docker-compose.yaml rename to tests/integration/merge/volumes_merge/docker-compose.yaml diff --git a/tests/integration/volumes_merge/index.txt b/tests/integration/merge/volumes_merge/index.txt similarity index 100% rename from tests/integration/volumes_merge/index.txt rename to tests/integration/merge/volumes_merge/index.txt diff --git a/tests/integration/volumes_merge/override.txt b/tests/integration/merge/volumes_merge/override.txt similarity index 100% rename from tests/integration/volumes_merge/override.txt rename to tests/integration/merge/volumes_merge/override.txt diff --git a/tests/integration/volumes_merge/test_podman_compose_volumes_merge.py b/tests/integration/merge/volumes_merge/test_podman_compose_volumes_merge.py similarity index 100% rename from tests/integration/volumes_merge/test_podman_compose_volumes_merge.py rename to tests/integration/merge/volumes_merge/test_podman_compose_volumes_merge.py From 35dc395483ec216b24def74c456041c634aecdc4 Mon Sep 17 00:00:00 2001 From: Monika Kairaityte Date: Tue, 29 Apr 2025 12:51:27 +0300 Subject: [PATCH 3/6] tests/integration: Add reset tag service test Signed-off-by: Monika Kairaityte --- .../reset_tag_service/__init__.py | 1 + .../docker-compose.reset_service.yaml | 6 ++ .../reset_tag_service/docker-compose.yaml | 5 ++ .../test_podman_compose_reset_tag_service.py | 59 +++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 tests/integration/merge/reset_and_override_tags/reset_tag_service/__init__.py create mode 100644 tests/integration/merge/reset_and_override_tags/reset_tag_service/docker-compose.reset_service.yaml create mode 100644 tests/integration/merge/reset_and_override_tags/reset_tag_service/docker-compose.yaml create mode 100644 tests/integration/merge/reset_and_override_tags/reset_tag_service/test_podman_compose_reset_tag_service.py diff --git a/tests/integration/merge/reset_and_override_tags/reset_tag_service/__init__.py b/tests/integration/merge/reset_and_override_tags/reset_tag_service/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/reset_tag_service/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/integration/merge/reset_and_override_tags/reset_tag_service/docker-compose.reset_service.yaml b/tests/integration/merge/reset_and_override_tags/reset_tag_service/docker-compose.reset_service.yaml new file mode 100644 index 0000000..2a8b86f --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/reset_tag_service/docker-compose.reset_service.yaml @@ -0,0 +1,6 @@ +version: "3" +services: + app: !reset + app2: + image: busybox + command: ["/bin/busybox", "echo", "One"] diff --git a/tests/integration/merge/reset_and_override_tags/reset_tag_service/docker-compose.yaml b/tests/integration/merge/reset_and_override_tags/reset_tag_service/docker-compose.yaml new file mode 100644 index 0000000..f1e8ba6 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/reset_tag_service/docker-compose.yaml @@ -0,0 +1,5 @@ +version: "3" +services: + app: + image: busybox + command: ["/bin/busybox", "echo", "Zero"] diff --git a/tests/integration/merge/reset_and_override_tags/reset_tag_service/test_podman_compose_reset_tag_service.py b/tests/integration/merge/reset_and_override_tags/reset_tag_service/test_podman_compose_reset_tag_service.py new file mode 100644 index 0000000..d840291 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/reset_tag_service/test_podman_compose_reset_tag_service.py @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: GPL-2.0 + +import os +import unittest + +from tests.integration.test_utils import RunSubprocessMixin +from tests.integration.test_utils import podman_compose_path +from tests.integration.test_utils import test_path + + +def compose_yaml_path(): + return os.path.join(os.path.join(test_path(), "reset_tag_service"), "docker-compose.yaml") + + +class TestComposeResetTagService(unittest.TestCase, RunSubprocessMixin): + # test if whole service from docker-compose.yaml file is reset + def test_reset_tag_service(self): + reset_file = os.path.join( + os.path.join(test_path(), "reset_tag_service"), "docker-compose.reset_service.yaml" + ) + try: + self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "-f", + reset_file, + "up", + ]) + + # app service was fully reset in docker-compose.reset_tag_service.yaml file, therefore + # does not exist. A new service was created instead. + output, _ = self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "-f", + reset_file, + "ps", + ]) + self.assertNotIn(b"reset_tag_service_app_1", output) + self.assertIn(b"reset_tag_service_app2_1", output) + + output, _ = self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "-f", + reset_file, + "logs", + ]) + self.assertEqual(output, b"One\n") + finally: + self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "down", + ]) From 5ab734026c19cb88852743d0272bd76588b1a921 Mon Sep 17 00:00:00 2001 From: Monika Kairaityte Date: Tue, 29 Apr 2025 15:32:46 +0300 Subject: [PATCH 4/6] tests/integration: Add reset tag attribute test Signed-off-by: Monika Kairaityte --- .../reset_tag_attribute/__init__.py | 1 + .../docker-compose.reset_attribute.yaml | 5 ++ .../reset_tag_attribute/docker-compose.yaml | 5 ++ ...test_podman_compose_reset_tag_attribute.py | 58 +++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 tests/integration/merge/reset_and_override_tags/reset_tag_attribute/__init__.py create mode 100644 tests/integration/merge/reset_and_override_tags/reset_tag_attribute/docker-compose.reset_attribute.yaml create mode 100644 tests/integration/merge/reset_and_override_tags/reset_tag_attribute/docker-compose.yaml create mode 100644 tests/integration/merge/reset_and_override_tags/reset_tag_attribute/test_podman_compose_reset_tag_attribute.py diff --git a/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/__init__.py b/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/docker-compose.reset_attribute.yaml b/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/docker-compose.reset_attribute.yaml new file mode 100644 index 0000000..1527a31 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/docker-compose.reset_attribute.yaml @@ -0,0 +1,5 @@ +version: "3" +services: + app: + image: busybox + command: !reset {} diff --git a/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/docker-compose.yaml b/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/docker-compose.yaml new file mode 100644 index 0000000..f1e8ba6 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/docker-compose.yaml @@ -0,0 +1,5 @@ +version: "3" +services: + app: + image: busybox + command: ["/bin/busybox", "echo", "Zero"] diff --git a/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/test_podman_compose_reset_tag_attribute.py b/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/test_podman_compose_reset_tag_attribute.py new file mode 100644 index 0000000..9c9634c --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/reset_tag_attribute/test_podman_compose_reset_tag_attribute.py @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0 + +import os +import unittest + +from tests.integration.test_utils import RunSubprocessMixin +from tests.integration.test_utils import podman_compose_path +from tests.integration.test_utils import test_path + + +def compose_yaml_path(): + return os.path.join(os.path.join(test_path(), "reset_tag_attribute"), "docker-compose.yaml") + + +class TestComposeResetTagAttribute(unittest.TestCase, RunSubprocessMixin): + # test if the attribute of the service is correctly reset + def test_reset_tag_attribute(self): + reset_file = os.path.join( + os.path.join(test_path(), "reset_tag_attribute"), "docker-compose.reset_attribute.yaml" + ) + try: + self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "-f", + reset_file, + "up", + ]) + + # the service still exists, but its command attribute was reset in + # docker-compose.reset_tag_attribute.yaml file and is now empty + output, _ = self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "-f", + reset_file, + "ps", + ]) + self.assertIn(b"reset_tag_attribute_app_1", output) + + output, _ = self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "-f", + reset_file, + "logs", + ]) + self.assertEqual(output, b"") + finally: + self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "down", + ]) From 2a33ef5c79d97cb0f6cf71213106d2de44f0bfc1 Mon Sep 17 00:00:00 2001 From: Monika Kairaityte Date: Tue, 29 Apr 2025 19:57:07 +0300 Subject: [PATCH 5/6] tests/integration: Add override tag service test Signed-off-by: Monika Kairaityte --- .../override_tag_service/__init__.py | 1 + .../docker-compose.override_service.yaml | 7 +++ .../override_tag_service/docker-compose.yaml | 7 +++ ...est_podman_compose_override_tag_service.py | 61 +++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 tests/integration/merge/reset_and_override_tags/override_tag_service/__init__.py create mode 100644 tests/integration/merge/reset_and_override_tags/override_tag_service/docker-compose.override_service.yaml create mode 100644 tests/integration/merge/reset_and_override_tags/override_tag_service/docker-compose.yaml create mode 100644 tests/integration/merge/reset_and_override_tags/override_tag_service/test_podman_compose_override_tag_service.py diff --git a/tests/integration/merge/reset_and_override_tags/override_tag_service/__init__.py b/tests/integration/merge/reset_and_override_tags/override_tag_service/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/override_tag_service/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/integration/merge/reset_and_override_tags/override_tag_service/docker-compose.override_service.yaml b/tests/integration/merge/reset_and_override_tags/override_tag_service/docker-compose.override_service.yaml new file mode 100644 index 0000000..630ec29 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/override_tag_service/docker-compose.override_service.yaml @@ -0,0 +1,7 @@ +version: "3" +services: + app: !override + image: busybox + command: ["/bin/busybox", "echo", "One"] + ports: + - "8111:81" diff --git a/tests/integration/merge/reset_and_override_tags/override_tag_service/docker-compose.yaml b/tests/integration/merge/reset_and_override_tags/override_tag_service/docker-compose.yaml new file mode 100644 index 0000000..74eaad0 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/override_tag_service/docker-compose.yaml @@ -0,0 +1,7 @@ +version: "3" +services: + app: + image: busybox + command: ["/bin/busybox", "echo", "Zero"] + ports: + - "8080:80" diff --git a/tests/integration/merge/reset_and_override_tags/override_tag_service/test_podman_compose_override_tag_service.py b/tests/integration/merge/reset_and_override_tags/override_tag_service/test_podman_compose_override_tag_service.py new file mode 100644 index 0000000..e39687c --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/override_tag_service/test_podman_compose_override_tag_service.py @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0 + +import json +import os +import unittest + +from tests.integration.test_utils import RunSubprocessMixin +from tests.integration.test_utils import podman_compose_path +from tests.integration.test_utils import test_path + + +def compose_yaml_path(): + return os.path.join(os.path.join(test_path(), "override_tag_service"), "docker-compose.yaml") + + +class TestComposeOverrideTagService(unittest.TestCase, RunSubprocessMixin): + # test if whole service from docker-compose.yaml file is overridden in another file + def test_override_tag_service(self): + override_file = os.path.join( + os.path.join(test_path(), "override_tag_service"), + "docker-compose.override_service.yaml", + ) + try: + self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "-f", + override_file, + "up", + ]) + + # Whole app service was overridden in the docker-compose.override_tag_service.yaml file. + # Command and port is overridden accordingly. + output, _ = self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "-f", + override_file, + "logs", + ]) + self.assertEqual(output, b"One\n") + + output, _ = self.run_subprocess_assert_returncode([ + "podman", + "inspect", + "override_tag_service_app_1", + ]) + container_info = json.loads(output.decode('utf-8'))[0] + self.assertEqual( + container_info['NetworkSettings']["Ports"], + {"81/tcp": [{"HostIp": "", "HostPort": "8111"}]}, + ) + finally: + self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "down", + ]) From 1dab256cddb496fbddc1a34fdc9d28e9dfd18850 Mon Sep 17 00:00:00 2001 From: Monika Kairaityte Date: Wed, 30 Apr 2025 17:20:00 +0300 Subject: [PATCH 6/6] tests/integration: Add override tag attribute test Signed-off-by: Monika Kairaityte --- .../override_tag_attribute/__init__.py | 1 + .../docker-compose.override_attribute.yaml | 7 +++ .../docker-compose.yaml | 7 +++ ...t_podman_compose_override_tag_attribute.py | 60 +++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 tests/integration/merge/reset_and_override_tags/override_tag_attribute/__init__.py create mode 100644 tests/integration/merge/reset_and_override_tags/override_tag_attribute/docker-compose.override_attribute.yaml create mode 100644 tests/integration/merge/reset_and_override_tags/override_tag_attribute/docker-compose.yaml create mode 100644 tests/integration/merge/reset_and_override_tags/override_tag_attribute/test_podman_compose_override_tag_attribute.py diff --git a/tests/integration/merge/reset_and_override_tags/override_tag_attribute/__init__.py b/tests/integration/merge/reset_and_override_tags/override_tag_attribute/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/override_tag_attribute/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/integration/merge/reset_and_override_tags/override_tag_attribute/docker-compose.override_attribute.yaml b/tests/integration/merge/reset_and_override_tags/override_tag_attribute/docker-compose.override_attribute.yaml new file mode 100644 index 0000000..17fb319 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/override_tag_attribute/docker-compose.override_attribute.yaml @@ -0,0 +1,7 @@ +version: "3" +services: + app: + image: busybox + command: ["/bin/busybox", "echo", "One"] + ports: !override + - "8111:81" diff --git a/tests/integration/merge/reset_and_override_tags/override_tag_attribute/docker-compose.yaml b/tests/integration/merge/reset_and_override_tags/override_tag_attribute/docker-compose.yaml new file mode 100644 index 0000000..74eaad0 --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/override_tag_attribute/docker-compose.yaml @@ -0,0 +1,7 @@ +version: "3" +services: + app: + image: busybox + command: ["/bin/busybox", "echo", "Zero"] + ports: + - "8080:80" diff --git a/tests/integration/merge/reset_and_override_tags/override_tag_attribute/test_podman_compose_override_tag_attribute.py b/tests/integration/merge/reset_and_override_tags/override_tag_attribute/test_podman_compose_override_tag_attribute.py new file mode 100644 index 0000000..3819f2c --- /dev/null +++ b/tests/integration/merge/reset_and_override_tags/override_tag_attribute/test_podman_compose_override_tag_attribute.py @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0 + +import json +import os +import unittest + +from tests.integration.test_utils import RunSubprocessMixin +from tests.integration.test_utils import podman_compose_path +from tests.integration.test_utils import test_path + + +def compose_yaml_path(): + return os.path.join(os.path.join(test_path(), "override_tag_attribute"), "docker-compose.yaml") + + +class TestComposeOverrideTagAttribute(unittest.TestCase, RunSubprocessMixin): + # test if a service attribute from docker-compose.yaml file is overridden + def test_override_tag_attribute(self): + override_file = os.path.join( + os.path.join(test_path(), "override_tag_attribute"), + "docker-compose.override_attribute.yaml", + ) + try: + self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "-f", + override_file, + "up", + ]) + # merge rules are still applied + output, _ = self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "-f", + override_file, + "logs", + ]) + self.assertEqual(output, b"One\n") + + # only app service attribute "ports" was overridden + output, _ = self.run_subprocess_assert_returncode([ + "podman", + "inspect", + "override_tag_attribute_app_1", + ]) + container_info = json.loads(output.decode('utf-8'))[0] + self.assertEqual( + container_info['NetworkSettings']["Ports"], + {"81/tcp": [{"HostIp": "", "HostPort": "8111"}]}, + ) + finally: + self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "down", + ])