← Back to team overview

sts-sponsors team mailing list archive

[Merge] ~adam-collard/maas-ci/+git/system-tests:lxd-file-stdin-stdout into ~maas-committers/maas-ci/+git/system-tests:master

 

Adam Collard has proposed merging ~adam-collard/maas-ci/+git/system-tests:lxd-file-stdin-stdout into ~maas-committers/maas-ci/+git/system-tests:master.

Commit message:
[lxd] Use stdin/stdout to push and pull files


Requested reviews:
  MAAS Committers (maas-committers)

For more details, see:
https://code.launchpad.net/~adam-collard/maas-ci/+git/system-tests/+merge/437428
-- 
Your team MAAS Committers is requested to review the proposed merge of ~adam-collard/maas-ci/+git/system-tests:lxd-file-stdin-stdout into ~maas-committers/maas-ci/+git/system-tests:master.
diff --git a/systemtests/lxd.py b/systemtests/lxd.py
index ccb1b2c..cd91678 100644
--- a/systemtests/lxd.py
+++ b/systemtests/lxd.py
@@ -1,9 +1,7 @@
 from __future__ import annotations
 
 import json
-import os
 import subprocess
-import tempfile
 import textwrap
 from functools import partial
 from itertools import chain
@@ -55,29 +53,24 @@ class _FileWrapper:
         return f"<FileWrapper for {self.path} on {self._instance}>"
 
     def read(self) -> str:
-        filename = os.path.basename(self.path)
-        with tempfile.TemporaryDirectory() as tempdir:
-            self._run(
-                [
-                    "lxc",
-                    "file",
-                    "--quiet",
-                    "pull",
-                    f"{self._instance.name}{self.path}",
-                    f"{tempdir}/",
-                ],
-            )
-            with open(os.path.join(tempdir, filename), "r") as f:
-                return f.read()
+        pull = self._run(
+            ["lxc", "file", "--quiet", "pull", f"{self._instance.name}{self.path}", "-"]
+        )
+        return pull.stdout
 
     def write(self, content: str, uid: int = 0, gid: int = 0) -> None:
-        with tempfile.NamedTemporaryFile() as source_file:
-            source_file.write(content.encode())
-            self.push(
-                Path(source_file.name),
-                uid=uid,
-                gid=gid,
-            )
+        args: list[str] = [
+            "--uid",
+            str(uid),
+            "--gid",
+            str(gid),
+            "--mode",
+            "",
+            "-",
+            f"{self._instance.name}{self.path}",
+        ]
+
+        self._run(["lxc", "file", "--quiet", "push", *args], stdin=content)
 
     def append(self, content: str) -> None:
         file_content = self.read().splitlines() if self.exists() else []
@@ -163,13 +156,14 @@ class Instance:
     def _run(
         self,
         cmd: list[str],
+        stdin: Optional[str] = None,
         prefix: Optional[list[str]] = None,
         logger: Optional[logging.Logger] = None,
     ) -> subprocess.CompletedProcess[str]:
         __tracebackhide__ = True
         if logger is None:
             logger = self.logger
-        return run_with_logging(cmd, logger, prefix=prefix)
+        return run_with_logging(cmd, logger, prefix=prefix, stdin=stdin)
 
     def exists(self) -> bool:
         try:
diff --git a/systemtests/subprocess.py b/systemtests/subprocess.py
index 51ef9a5..de427b0 100644
--- a/systemtests/subprocess.py
+++ b/systemtests/subprocess.py
@@ -15,6 +15,7 @@ def run_with_logging(
     logger: logging.Logger,
     env: Optional[dict[str, str]] = None,
     prefix: Optional[list[str]] = None,
+    stdin: Optional[str] = None,
 ) -> subprocess.CompletedProcess[str]:
     __tracebackhide__ = True
     if prefix is None:
@@ -22,17 +23,25 @@ def run_with_logging(
     logger.info("┌ " + " ".join(repr(arg) if "\n" in arg else arg for arg in cmd))
     process = subprocess.Popen(
         prefix + cmd,
+        stdin=subprocess.PIPE,
         stdout=subprocess.PIPE,
         stderr=subprocess.PIPE,
         encoding="utf-8",
         errors="backslashreplace",
         env=env,
     )
-    stdout = io.StringIO()
-    stderr = io.StringIO()
     # So mypy knows we've got real things
+    assert process.stdin is not None
     assert process.stdout is not None
     assert process.stderr is not None
+    if stdin is None:
+        process.stdin.close()
+    else:
+        with process.stdin as fd:
+            fd.write(stdin)
+
+    stdout = io.StringIO()
+    stderr = io.StringIO()
     sel = selectors.DefaultSelector()
     sel.register(process.stdout, selectors.EVENT_READ, ("|", stdout.write))
     sel.register(process.stderr, selectors.EVENT_READ, ("|E", stderr.write))

Follow ups