diff --git a/docs/Extensions.md b/docs/Extensions.md index 12b85b2..11f01c3 100644 --- a/docs/Extensions.md +++ b/docs/Extensions.md @@ -86,7 +86,7 @@ networks: - subnet: "192.168.1.0/24" services: - webserver + webserver: image: "busybox" command: ["/bin/busybox", "httpd", "-f", "-h", "/etc", "-p", "8001"] networks: @@ -98,6 +98,10 @@ services: mac_address: "02:bb:bb:bb:bb:bb" # mac_address is supported ``` +## Per-network interface name + +Using `x-podman.interface_name` within a containers network config you can specify the interface name inside the container. + ## Podman-specific network modes Generic docker-compose supports the following values for `network-mode` for a container: diff --git a/newsfragments/x-podman.interface_name.feature b/newsfragments/x-podman.interface_name.feature new file mode 100644 index 0000000..5a5e99d --- /dev/null +++ b/newsfragments/x-podman.interface_name.feature @@ -0,0 +1 @@ +- Add support for 'x-podman.interface_name' to allow setting the interface name for each network participation. diff --git a/podman_compose.py b/podman_compose.py index cd78288..5a0e138 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -989,6 +989,7 @@ def get_net_args_from_networks(compose, cnt): default_net_name = default_network_name_for_project(compose, net_, is_ext) net_name = ext_desc.get("name") or net_desc.get("name") or default_net_name + interface_name = net_config_.get("x-podman.interface_name") ipv4 = net_config_.get("ipv4_address") ipv6 = net_config_.get("ipv6_address") # Note: mac_address is supported by compose spec now, and x-podman.mac_address @@ -1006,6 +1007,8 @@ def get_net_args_from_networks(compose, cnt): mac_address = None net_options = [] + if interface_name: + net_options.append(f"interface_name={interface_name}") if ipv4: net_options.append(f"ip={ipv4}") if ipv6: diff --git a/tests/integration/network_interface_name/__init__.py b/tests/integration/network_interface_name/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/integration/network_interface_name/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/integration/network_interface_name/docker-compose.yml b/tests/integration/network_interface_name/docker-compose.yml new file mode 100644 index 0000000..5d1c4bf --- /dev/null +++ b/tests/integration/network_interface_name/docker-compose.yml @@ -0,0 +1,10 @@ +version: "3" +networks: + mystack: +services: + web: + image: busybox + command: ["/bin/busybox", "httpd", "-f", "-h", ".", "-p", "8004"] + networks: + mystack: + x-podman.interface_name: customName0 diff --git a/tests/integration/network_interface_name/test_podman_compose_network_interface_name.py b/tests/integration/network_interface_name/test_podman_compose_network_interface_name.py new file mode 100644 index 0000000..b87faef --- /dev/null +++ b/tests/integration/network_interface_name/test_podman_compose_network_interface_name.py @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0 + +# pylint: disable=redefined-outer-name +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 + + +class TestPodmanComposeNetworkInterfaceName(RunSubprocessMixin, unittest.TestCase): + def compose_file(self): + return os.path.join(test_path(), "network_interface_name", "docker-compose.yml") + + def up(self): + up_cmd = [ + "coverage", + "run", + podman_compose_path(), + "-f", + self.compose_file(), + "up", + "-d", + "--force-recreate", + ] + self.run_subprocess_assert_returncode(up_cmd) + + def down(self): + down_cmd = [ + "coverage", + "run", + podman_compose_path(), + "-f", + self.compose_file(), + "kill", + "-a", + ] + self.run_subprocess(down_cmd) + + def test_interface_name(self): + try: + self.up() + + interfaces_cmd = [ + podman_compose_path(), + "-f", + self.compose_file(), + "exec", + "web", + "ls", + "/sys/class/net", + "--color=never", + ] + out, _ = self.run_subprocess_assert_returncode(interfaces_cmd) + self.assertEqual("customName0 lo\r\n", out.decode()) + finally: + self.down()