File gh-pr525-nsdict.patch of Package python-podman

From 1510ab7921dfbcdf929144730102be8e97bd7295 Mon Sep 17 00:00:00 2001
From: "Jose D. Gomez R" <1josegomezr@gmail.com>
Date: Thu, 13 Mar 2025 10:39:37 +0100
Subject: [PATCH] feat: expose `*ns` keys to consumers

`cgroupns`, `ipcns`, `pidns`, `userns`, `utsns` now support setting the
`value` attribute.

This allows to mimic the behavior of `--userns`[0] cli arg via this API.

[0]: https://docs.podman.io/en/stable/markdown/podman-create.1.html#userns-mode

Signed-off-by: Jose D. Gomez R <1josegomezr@gmail.com>
---
 podman/domain/containers_create.py          | 17 +++++---
 podman/tests/unit/test_containersmanager.py | 48 +++++++++++++++++++++
 2 files changed, 60 insertions(+), 5 deletions(-)

diff --git a/podman/domain/containers_create.py b/podman/domain/containers_create.py
index 80d7f7c8..12b756fc 100644
--- a/podman/domain/containers_create.py
+++ b/podman/domain/containers_create.py
@@ -436,6 +436,13 @@ def _render_payload(kwargs: MutableMapping[str, Any]) -> dict[str, Any]:
         def pop(k):
             return args.pop(k, None)
 
+        def normalize_nsmode(
+            mode: Union[str, MutableMapping[str, str]],
+        ) -> dict[str, str]:
+            if isinstance(mode, dict):
+                return mode
+            return {"nsmode": mode}
+
         def to_bytes(size: Union[int, str, None]) -> Union[int, None]:
             """
             Converts str or int to bytes.
@@ -746,10 +753,10 @@ def parse_host_port(_container_port, _protocol, _host):
             params["secret_env"] = args.pop("secret_env", {})
 
         if "cgroupns" in args:
-            params["cgroupns"] = {"nsmode": args.pop("cgroupns")}
+            params["cgroupns"] = normalize_nsmode(args.pop("cgroupns"))
 
         if "ipc_mode" in args:
-            params["ipcns"] = {"nsmode": args.pop("ipc_mode")}
+            params["ipcns"] = normalize_nsmode(args.pop("ipc_mode"))
 
         if "network_mode" in args:
             network_mode = args.pop("network_mode")
@@ -760,13 +767,13 @@ def parse_host_port(_container_port, _protocol, _host):
                 params["netns"] = {"nsmode": network_mode}
 
         if "pid_mode" in args:
-            params["pidns"] = {"nsmode": args.pop("pid_mode")}
+            params["pidns"] = normalize_nsmode(args.pop("pid_mode"))
 
         if "userns_mode" in args:
-            params["userns"] = {"nsmode": args.pop("userns_mode")}
+            params["userns"] = normalize_nsmode(args.pop("userns_mode"))
 
         if "uts_mode" in args:
-            params["utsns"] = {"nsmode": args.pop("uts_mode")}
+            params["utsns"] = normalize_nsmode(args.pop("uts_mode"))
 
         if len(args) > 0:
             raise TypeError(
diff --git a/podman/tests/unit/test_containersmanager.py b/podman/tests/unit/test_containersmanager.py
index f72ac226..47b30482 100644
--- a/podman/tests/unit/test_containersmanager.py
+++ b/podman/tests/unit/test_containersmanager.py
@@ -257,6 +257,54 @@ def test_create_parse_host_port(self, mock):
         ]
         self.assertEqual(expected_ports, actual_ports)
 
+    @requests_mock.Mocker()
+    def test_create_userns_mode_simple(self, mock):
+        mock_response = MagicMock()
+        mock_response.json = lambda: {
+            "Id": "87e1325c82424e49a00abdd4de08009eb76c7de8d228426a9b8af9318ced5ecd",
+            "Size": 1024,
+        }
+        self.client.containers.client.post = MagicMock(return_value=mock_response)
+        mock.get(
+            tests.LIBPOD_URL
+            + "/containers/87e1325c82424e49a00abdd4de08009eb76c7de8d228426a9b8af9318ced5ecd/json",
+            json=FIRST_CONTAINER,
+        )
+
+        userns = "keep-id"
+        self.client.containers.create("fedora", "/usr/bin/ls", userns_mode=userns)
+        self.client.containers.client.post.assert_called()
+        expected_userns = {"nsmode": userns}
+
+        actual_userns = json.loads(self.client.containers.client.post.call_args[1]["data"])[
+            "userns"
+        ]
+        self.assertEqual(expected_userns, actual_userns)
+
+    @requests_mock.Mocker()
+    def test_create_userns_mode_dict(self, mock):
+        mock_response = MagicMock()
+        mock_response.json = lambda: {
+            "Id": "87e1325c82424e49a00abdd4de08009eb76c7de8d228426a9b8af9318ced5ecd",
+            "Size": 1024,
+        }
+        self.client.containers.client.post = MagicMock(return_value=mock_response)
+        mock.get(
+            tests.LIBPOD_URL
+            + "/containers/87e1325c82424e49a00abdd4de08009eb76c7de8d228426a9b8af9318ced5ecd/json",
+            json=FIRST_CONTAINER,
+        )
+
+        userns = {"nsmode": "keep-id", "value": "uid=900"}
+        self.client.containers.create("fedora", "/usr/bin/ls", userns_mode=userns)
+        self.client.containers.client.post.assert_called()
+        expected_userns = dict(**userns)
+
+        actual_userns = json.loads(self.client.containers.client.post.call_args[1]["data"])[
+            "userns"
+        ]
+        self.assertEqual(expected_userns, actual_userns)
+
     def test_create_unsupported_key(self):
         with self.assertRaises(TypeError):
             self.client.containers.create("fedora", "/usr/bin/ls", blkio_weight=100.0)
openSUSE Build Service is sponsored by