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)