From 853be4362d563c70b061fad3d9e83572a183039a Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sun, 6 Jul 2025 19:48:15 +0300 Subject: [PATCH 1/3] docs: Fix typo in x-podman.disable_dns Signed-off-by: Povilas Kanapickas --- docs/Extensions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Extensions.md b/docs/Extensions.md index 879d0b4..3e25e0d 100644 --- a/docs/Extensions.md +++ b/docs/Extensions.md @@ -47,8 +47,8 @@ For explanations of these extensions, please refer to the [podman-run --volume d The following extension keys are available under network configuration: -* `x-podman.disable-dns` - Disable the DNS plugin for the network when set to 'true'. -* `x-podman.dns` - Set nameservers for the network using supplied addresses (cannot be used with x-podman.disable-dns`). +* `x-podman.disable_dns` - Disable the DNS plugin for the network when set to 'true'. +* `x-podman.dns` - Specifies a list of nameservers for the network This cannot be used with x-podman.disable_dns`. For example, the following docker-compose.yml allows all containers on the same network to use the specified nameservers: From c7bce311db8dc9571c09914400b58b20def2437c Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sun, 6 Jul 2025 19:48:16 +0300 Subject: [PATCH 2/3] tests: Extract get_minimal_net_desc() in network tests Signed-off-by: Povilas Kanapickas --- tests/unit/test_get_network_create_args.py | 112 +++++++-------------- 1 file changed, 37 insertions(+), 75 deletions(-) diff --git a/tests/unit/test_get_network_create_args.py b/tests/unit/test_get_network_create_args.py index b06f4fc..df00840 100644 --- a/tests/unit/test_get_network_create_args.py +++ b/tests/unit/test_get_network_create_args.py @@ -1,11 +1,12 @@ import unittest +from typing import Any from podman_compose import get_network_create_args class TestGetNetworkCreateArgs(unittest.TestCase): - def test_minimal(self) -> None: - net_desc = { + def get_minimal_net_desc(self) -> dict[str, Any]: + return { "labels": [], "internal": False, "driver": None, @@ -13,6 +14,9 @@ class TestGetNetworkCreateArgs(unittest.TestCase): "ipam": {"config": []}, "enable_ipv6": False, } + + def test_minimal(self) -> None: + net_desc = self.get_minimal_net_desc() proj_name = "test_project" net_name = "test_network" expected_args = [ @@ -27,14 +31,8 @@ class TestGetNetworkCreateArgs(unittest.TestCase): self.assertEqual(args, expected_args) def test_ipv6(self) -> None: - net_desc = { - "labels": [], - "internal": False, - "driver": None, - "driver_opts": {}, - "ipam": {"config": []}, - "enable_ipv6": True, - } + net_desc = self.get_minimal_net_desc() + net_desc["enable_ipv6"] = True proj_name = "test_project" net_name = "test_network" expected_args = [ @@ -50,14 +48,9 @@ class TestGetNetworkCreateArgs(unittest.TestCase): self.assertEqual(args, expected_args) def test_bridge(self) -> None: - net_desc = { - "labels": [], - "internal": False, - "driver": "bridge", - "driver_opts": {"opt1": "value1", "opt2": "value2"}, - "ipam": {"config": []}, - "enable_ipv6": False, - } + net_desc = self.get_minimal_net_desc() + net_desc["driver"] = "bridge" + net_desc["driver_opts"] = {"opt1": "value1", "opt2": "value2"} proj_name = "test_project" net_name = "test_network" expected_args = [ @@ -78,21 +71,16 @@ class TestGetNetworkCreateArgs(unittest.TestCase): self.assertEqual(args, expected_args) def test_ipam_driver_default(self) -> None: - net_desc = { - "labels": [], - "internal": False, - "driver": None, - "driver_opts": {}, - "ipam": { - "driver": "default", - "config": [ - { - "subnet": "192.168.0.0/24", - "ip_range": "192.168.0.2/24", - "gateway": "192.168.0.1", - } - ], - }, + net_desc = self.get_minimal_net_desc() + net_desc["ipam"] = { + "driver": "default", + "config": [ + { + "subnet": "192.168.0.0/24", + "ip_range": "192.168.0.2/24", + "gateway": "192.168.0.1", + } + ], } proj_name = "test_project" net_name = "test_network" @@ -114,21 +102,16 @@ class TestGetNetworkCreateArgs(unittest.TestCase): self.assertEqual(args, expected_args) def test_ipam_driver(self) -> None: - net_desc = { - "labels": [], - "internal": False, - "driver": None, - "driver_opts": {}, - "ipam": { - "driver": "someipamdriver", - "config": [ - { - "subnet": "192.168.0.0/24", - "ip_range": "192.168.0.2/24", - "gateway": "192.168.0.1", - } - ], - }, + net_desc = self.get_minimal_net_desc() + net_desc["ipam"] = { + "driver": "someipamdriver", + "config": [ + { + "subnet": "192.168.0.0/24", + "ip_range": "192.168.0.2/24", + "gateway": "192.168.0.1", + } + ], } proj_name = "test_project" net_name = "test_network" @@ -203,15 +186,8 @@ class TestGetNetworkCreateArgs(unittest.TestCase): self.assertEqual(args, expected_args) def test_disable_dns(self) -> None: - net_desc = { - "labels": [], - "internal": False, - "driver": None, - "driver_opts": {}, - "ipam": {"config": []}, - "enable_ipv6": False, - "x-podman.disable_dns": True, - } + net_desc = self.get_minimal_net_desc() + net_desc["x-podman.disable_dns"] = True proj_name = "test_project" net_name = "test_network" expected_args = [ @@ -227,15 +203,8 @@ class TestGetNetworkCreateArgs(unittest.TestCase): self.assertEqual(args, expected_args) def test_dns_string(self) -> None: - net_desc = { - "labels": [], - "internal": False, - "driver": None, - "driver_opts": {}, - "ipam": {"config": []}, - "enable_ipv6": False, - "x-podman.dns": "192.168.1.2", - } + net_desc = self.get_minimal_net_desc() + net_desc["x-podman.dns"] = "192.168.1.2" proj_name = "test_project" net_name = "test_network" expected_args = [ @@ -252,15 +221,8 @@ class TestGetNetworkCreateArgs(unittest.TestCase): self.assertEqual(args, expected_args) def test_dns_list(self) -> None: - net_desc = { - "labels": [], - "internal": False, - "driver": None, - "driver_opts": {}, - "ipam": {"config": []}, - "enable_ipv6": False, - "x-podman.dns": ["192.168.1.2", "192.168.1.3"], - } + net_desc = self.get_minimal_net_desc() + net_desc["x-podman.dns"] = ["192.168.1.2", "192.168.1.3"] proj_name = "test_project" net_name = "test_network" expected_args = [ From 8113a16bafbab11af51439c6237a1fe0189d6750 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sun, 6 Jul 2025 19:48:17 +0300 Subject: [PATCH 3/3] Add support to set --route of podman network create This is not present in the compose spec. However, netavark podman network backend does support --route option, which is useful for various kinds of things. It is very easy to expose it. Signed-off-by: Povilas Kanapickas --- docs/Extensions.md | 13 +++++++ newsfragments/x-podman-network-routes.feature | 2 + podman_compose.py | 4 ++ tests/unit/test_get_network_create_args.py | 38 +++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 newsfragments/x-podman-network-routes.feature diff --git a/docs/Extensions.md b/docs/Extensions.md index 3e25e0d..4626a30 100644 --- a/docs/Extensions.md +++ b/docs/Extensions.md @@ -61,6 +61,19 @@ network: - "10.1.2.4" ``` +* `x-podman.routes` - Specifies a list of additional routes for the network. This corresponds to + `--route` option in `podman network create`. + +For example, the following docker-compose.yml blocks network connectivity to specified subnet from +all containers on the network: +```yml +version: "3" +network: + my_network: + x-podman.routes: + - "10.2.3.4,127.0.0.1" +``` + For explanations of these extensions, please refer to the [Podman network create command Documentation](https://docs.podman.io/en/latest/markdown/podman-network-create.1.html). diff --git a/newsfragments/x-podman-network-routes.feature b/newsfragments/x-podman-network-routes.feature new file mode 100644 index 0000000..6ceca20 --- /dev/null +++ b/newsfragments/x-podman-network-routes.feature @@ -0,0 +1,2 @@ +Added support to set `--route` option to `podman network create` via +`x-podman.routes` key on network configuration. \ No newline at end of file diff --git a/podman_compose.py b/podman_compose.py index e9534b3..738c907 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -898,6 +898,10 @@ def get_network_create_args(net_desc: dict[str, Any], proj_name: str, net_name: "--dns", ",".join(norm_as_list(net_desc.get("x-podman.dns"))), )) + if net_desc.get("x-podman.routes"): + routes = norm_as_list(net_desc.get("x-podman.routes")) + for route in routes: + args.extend(["--route", route]) if isinstance(ipam_config_ls, dict): ipam_config_ls = [ipam_config_ls] diff --git a/tests/unit/test_get_network_create_args.py b/tests/unit/test_get_network_create_args.py index df00840..aab37b4 100644 --- a/tests/unit/test_get_network_create_args.py +++ b/tests/unit/test_get_network_create_args.py @@ -237,3 +237,41 @@ class TestGetNetworkCreateArgs(unittest.TestCase): ] args = get_network_create_args(net_desc, proj_name, net_name) self.assertEqual(args, expected_args) + + def test_routes_string(self) -> None: + net_desc = self.get_minimal_net_desc() + net_desc["x-podman.routes"] = "192.168.1.0/24" + proj_name = "test_project" + net_name = "test_network" + expected_args = [ + "create", + "--label", + f"io.podman.compose.project={proj_name}", + "--label", + f"com.docker.compose.project={proj_name}", + "--route", + "192.168.1.0/24", + net_name, + ] + args = get_network_create_args(net_desc, proj_name, net_name) + self.assertEqual(args, expected_args) + + def test_routes_list(self) -> None: + net_desc = self.get_minimal_net_desc() + net_desc["x-podman.routes"] = ["192.168.1.0/24", "192.168.2.0/24"] + proj_name = "test_project" + net_name = "test_network" + expected_args = [ + "create", + "--label", + f"io.podman.compose.project={proj_name}", + "--label", + f"com.docker.compose.project={proj_name}", + "--route", + "192.168.1.0/24", + "--route", + "192.168.2.0/24", + net_name, + ] + args = get_network_create_args(net_desc, proj_name, net_name) + self.assertEqual(args, expected_args)