diff --git a/newsfragments/fix_external_network_name_dict.bugfix b/newsfragments/fix_external_network_name_dict.bugfix new file mode 100644 index 00000000..d21c8277 --- /dev/null +++ b/newsfragments/fix_external_network_name_dict.bugfix @@ -0,0 +1 @@ +Fix external networks with `name:` key being ignored, causing `podman-compose` to look up the wrong (auto-prefixed) network name instead of the explicitly provided one. diff --git a/podman_compose.py b/podman_compose.py index 307804b9..69af58ad 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -1296,7 +1296,7 @@ def get_net_args_from_networks(compose: PodmanCompose, cnt: dict[str, Any]) -> l for net_, net_config_ in multiple_nets.items(): net_desc = compose.networks.get(net_) or {} is_ext = net_desc.get("external") - ext_desc: dict[str, Any] = is_ext if isinstance(is_ext, str) else {} # type: ignore[assignment] + ext_desc: dict[str, Any] = is_ext if isinstance(is_ext, dict) else {} # type: ignore[assignment] default_net_name = default_network_name_for_project(compose, net_, is_ext) # type: ignore[arg-type] net_name = ext_desc.get("name") or net_desc.get("name") or default_net_name diff --git a/tests/integration/external_network_name/__init__.py b/tests/integration/external_network_name/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/integration/external_network_name/docker-compose.yml b/tests/integration/external_network_name/docker-compose.yml new file mode 100644 index 00000000..599574c6 --- /dev/null +++ b/tests/integration/external_network_name/docker-compose.yml @@ -0,0 +1,10 @@ +services: + web: + image: nopush/podman-compose-test + command: ["dumb-init", "/bin/busybox", "httpd", "-f", "-p", "8123", "-h", "/tmp/"] + networks: + - backend_net +networks: + backend_net: + external: + name: external_network_name_backend diff --git a/tests/integration/external_network_name/test_external_network_name.py b/tests/integration/external_network_name/test_external_network_name.py new file mode 100644 index 00000000..b102374a --- /dev/null +++ b/tests/integration/external_network_name/test_external_network_name.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() -> str: + return os.path.join(os.path.join(test_path(), "external_network_name"), "docker-compose.yml") + + +class TestExternalNetworkName(unittest.TestCase, RunSubprocessMixin): + def test_external_network_with_name(self) -> None: + # Pre-create the external network + self.run_subprocess_assert_returncode( + ["podman", "network", "create", "external_network_name_backend"], + ) + try: + self.run_subprocess_assert_returncode( + [podman_compose_path(), "-f", compose_yaml_path(), "up", "-d"], + ) + + container_id_out, _ = self.run_subprocess_assert_returncode( + [ + podman_compose_path(), + "-f", + compose_yaml_path(), + "ps", + "--format", + '{{.ID}}', + ], + ) + container_id = container_id_out.decode('utf-8').split('\n')[0] + output, _ = self.run_subprocess_assert_returncode( + [ + "podman", + "inspect", + container_id, + "--format", + "{{range $key, $value := .NetworkSettings.Networks }}{{ $key }}\n{{ end }}", + ], + ) + self.assertEqual(output.decode('utf-8').strip(), "external_network_name_backend") + finally: + self.run_subprocess_assert_returncode([ + podman_compose_path(), + "-f", + compose_yaml_path(), + "down", + "-t", + "0", + ]) + self.run_subprocess_assert_returncode( + ["podman", "network", "rm", "-f", "external_network_name_backend"], + ) diff --git a/tests/unit/test_get_net_args.py b/tests/unit/test_get_net_args.py index 05205abf..f2e5fc3d 100644 --- a/tests/unit/test_get_net_args.py +++ b/tests/unit/test_get_net_args.py @@ -326,3 +326,33 @@ def test_network__mode_service(self) -> None: container["network_mode"] = "service:service_2" self.assertEqual(get_net_args(compose, container), ["--network=container:container_2"]) + + def test_external_network_with_name_dict(self) -> None: + """external: name: custom-network should use the custom name, not the prefixed one.""" + compose = get_networked_compose(num_networks=1) + compose.networks["net0"] = { + "external": {"name": "my-external-net"}, + } + compose.default_net = None + container = get_minimal_container() + container["networks"] = {"net0": {}} + + self.assertEqual( + get_net_args(compose, container), + ["--network=my-external-net:alias=service_name"], + ) + + def test_external_network_bool_true(self) -> None: + """external: true should use the un-prefixed compose key as the network name.""" + compose = get_networked_compose(num_networks=1) + compose.networks["net0"] = { + "external": True, + } + compose.default_net = None + container = get_minimal_container() + container["networks"] = {"net0": {}} + + self.assertEqual( + get_net_args(compose, container), + ["--network=net0:alias=service_name"], + )