From 98f166d2e46ab9fb93a2d46516c106c00fff1f95 Mon Sep 17 00:00:00 2001 From: Elsa Date: Tue, 8 Apr 2025 20:44:27 +0800 Subject: [PATCH] Implement pids_limit Signed-off-by: Elsa --- .../1182-implement-pids-limit.feature | 1 + podman_compose.py | 16 +++++ tests/unit/test_container_to_args.py | 64 +++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 newsfragments/1182-implement-pids-limit.feature diff --git a/newsfragments/1182-implement-pids-limit.feature b/newsfragments/1182-implement-pids-limit.feature new file mode 100644 index 0000000..94823e4 --- /dev/null +++ b/newsfragments/1182-implement-pids-limit.feature @@ -0,0 +1 @@ +- Add support for `pids_limit` and `deploy.resources.limits.pids` \ No newline at end of file diff --git a/podman_compose.py b/podman_compose.py index b2c36bc..5a5e18b 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -771,6 +771,22 @@ def container_to_cpu_res_args(cnt, podman_args): str(mem_res).lower(), )) + # Handle pids limit from both container level and deploy section + pids_limit = cnt.get("pids_limit") + deploy_pids = limits.get("pids") + + # Ensure consistency between pids_limit and deploy.resources.limits.pids + if pids_limit is not None and deploy_pids is not None: + if str(pids_limit) != str(deploy_pids): + raise ValueError( + f"Inconsistent PIDs limit: pids_limit ({pids_limit}) and " + f"deploy.resources.limits.pids ({deploy_pids}) must be the same" + ) + + final_pids_limit = pids_limit if pids_limit is not None else deploy_pids + if final_pids_limit is not None: + podman_args.extend(["--pids-limit", str(final_pids_limit)]) + def port_dict_to_str(port_desc): # NOTE: `mode: host|ingress` is ignored diff --git a/tests/unit/test_container_to_args.py b/tests/unit/test_container_to_args.py index f241cb5..ee07b92 100644 --- a/tests/unit/test_container_to_args.py +++ b/tests/unit/test_container_to_args.py @@ -630,3 +630,67 @@ class TestContainerToArgs(unittest.IsolatedAsyncioTestCase): "busybox", ], ) + + async def test_pids_limit_container_level(self): + c = create_compose_mock() + cnt = get_minimal_container() + cnt["pids_limit"] = 100 + + args = await container_to_args(c, cnt) + self.assertEqual( + args, + [ + "--name=project_name_service_name1", + "-d", + "--network=bridge:alias=service_name", + "--pids-limit", + "100", + "busybox", + ], + ) + + async def test_pids_limit_deploy_section(self): + c = create_compose_mock() + cnt = get_minimal_container() + cnt["deploy"] = {"resources": {"limits": {"pids": 100}}} + + args = await container_to_args(c, cnt) + self.assertEqual( + args, + [ + "--name=project_name_service_name1", + "-d", + "--network=bridge:alias=service_name", + "--pids-limit", + "100", + "busybox", + ], + ) + + async def test_pids_limit_both_same(self): + c = create_compose_mock() + cnt = get_minimal_container() + cnt["pids_limit"] = 100 + cnt["deploy"] = {"resources": {"limits": {"pids": 100}}} + + args = await container_to_args(c, cnt) + self.assertEqual( + args, + [ + "--name=project_name_service_name1", + "-d", + "--network=bridge:alias=service_name", + "--pids-limit", + "100", + "busybox", + ], + ) + + async def test_pids_limit_both_different(self): + c = create_compose_mock() + cnt = get_minimal_container() + cnt["pids_limit"] = 100 + cnt["deploy"] = {"resources": {"limits": {"pids": 200}}} + + with self.assertRaises(ValueError): + await container_to_args(c, cnt)