Repository: proxmoxer/proxmoxer

Issue:
SSH backends choke on bytes as parameters
If bytes are passed as parameters to proxmoxer, they end up formatted like `b'this is a parameter'` instead of `this is a parameter`.  This makes pvesh choke when the actual API call is made.

I have a fix, will create PR immediately after this ticket.

Discussion:
jhollowe: Please add tests for this new functionality
asdorsey: Test added, it's basically a copy of `test_request_data` but with the data value in bytes format.

Patch:
diff --git a/proxmoxer/backends/command_base.py b/proxmoxer/backends/command_base.py
index f8ca4a5..4d8e7b0 100644
--- a/proxmoxer/backends/command_base.py
+++ b/proxmoxer/backends/command_base.py
@@ -88,7 +88,12 @@ class CommandBaseSession:
 
         command = [f"{self.service}sh", cmd, url]
         # convert the options dict into a 2-tuple with the key formatted as a flag
-        option_pairs = [(f"-{k}", str(v)) for k, v in chain(data.items(), params.items())]
+        option_pairs = []
+        for k, v in chain(data.items(), params.items()):
+            try:
+                option_pairs.append((f"-{k}", str(v, "utf-8")))
+            except TypeError:
+                option_pairs.append((f"-{k}", str(v)))
         # add back in all the command arguments as their own pairs
         if data_command is not None:
             if isinstance(data_command, list):


Test patch:
diff --git a/tests/test_command_base.py b/tests/test_command_base.py
index c7b6b4a..6306eed 100644
--- a/tests/test_command_base.py
+++ b/tests/test_command_base.py
@@ -122,6 +122,22 @@ class TestCommandBaseSession:
             "json",
         ]
 
+    def test_request_bytes_data(self, mock_exec):
+        resp = self._session.request(
+            "GET", self.base_url + "/fake/echo", data={"key": b"bytes-value"}
+        )
+
+        assert resp.status_code == 200
+        assert resp.content == [
+            "pvesh",
+            "get",
+            self.base_url + "/fake/echo",
+            "-key",
+            "bytes-value",
+            "--output-format",
+            "json",
+        ]
+
     def test_request_qemu_exec(self, mock_exec):
         resp = self._session.request(
             "POST",