[lxc-devel] [pylxd/master] client: Add basic support for projects

d0ugal on Github lxc-bot at linuxcontainers.org
Mon Dec 7 10:43:25 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 567 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201207/6ef90489/attachment.bin>
-------------- next part --------------
From 1c39ede17b999b179988cdf7bb837a45e9ba23fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 7 Oct 2020 15:40:23 -0400
Subject: [PATCH] client: Add basic support for projects
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This allows passing the project name as a string to Client and have it
automatically added to all URLs.

Blackened by @d0ugal for easier merging.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
Signed-off-by: Dougal Matthews <dougal at dougalmatthews.com>
---
 pylxd/client.py | 61 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 56 insertions(+), 5 deletions(-)

diff --git a/pylxd/client.py b/pylxd/client.py
index c632db11..23890305 100644
--- a/pylxd/client.py
+++ b/pylxd/client.py
@@ -63,9 +63,12 @@ class EventType(Enum):
 class _APINode:
     """An api node object."""
 
-    def __init__(self, api_endpoint, cert=None, verify=True, timeout=None):
+    def __init__(
+        self, api_endpoint, cert=None, verify=True, timeout=None, project=None
+    ):
         self._api_endpoint = api_endpoint
         self._timeout = timeout
+        self._project = project
 
         if self._api_endpoint.startswith("http+unix://"):
             self.session = requests_unixsocket.Session()
@@ -91,6 +94,7 @@ def __getattr__(self, name):
             cert=self.session.cert,
             verify=self.session.verify,
             timeout=self._timeout,
+            project=self._project,
         )
 
     def __getitem__(self, item):
@@ -106,6 +110,7 @@ def __getitem__(self, item):
             cert=self.session.cert,
             verify=self.session.verify,
             timeout=self._timeout,
+            project=self._project,
         )
 
     def _assert_response(
@@ -163,6 +168,12 @@ def get(self, *args, **kwargs):
         """
         is_api = kwargs.pop("is_api", True)
         kwargs["timeout"] = kwargs.get("timeout", self._timeout)
+
+        if self._project is not None:
+            params = kwargs.get("params", {})
+            params["project"] = self._project
+            kwargs["params"] = params
+
         response = self.session.get(self._api_endpoint, *args, **kwargs)
         self._assert_response(
             response, stream=kwargs.get("stream", False), is_api=is_api
@@ -172,13 +183,18 @@ def get(self, *args, **kwargs):
     def post(self, *args, **kwargs):
         """Perform an HTTP POST."""
         kwargs["timeout"] = kwargs.get("timeout", self._timeout)
-        target = kwargs.pop("target", None)
 
+        target = kwargs.pop("target", None)
         if target is not None:
             params = kwargs.get("params", {})
             params["target"] = target
             kwargs["params"] = params
 
+        if self._project is not None:
+            params = kwargs.get("params", {})
+            params["project"] = self._project
+            kwargs["params"] = params
+
         response = self.session.post(self._api_endpoint, *args, **kwargs)
         # Prior to LXD 2.0.3, successful synchronous requests returned 200,
         # rather than 201.
@@ -188,6 +204,12 @@ def post(self, *args, **kwargs):
     def put(self, *args, **kwargs):
         """Perform an HTTP PUT."""
         kwargs["timeout"] = kwargs.get("timeout", self._timeout)
+
+        if self._project is not None:
+            params = kwargs.get("params", {})
+            params["project"] = self._project
+            kwargs["params"] = params
+
         response = self.session.put(self._api_endpoint, *args, **kwargs)
         self._assert_response(response, allowed_status_codes=(200, 202))
         return response
@@ -195,6 +217,12 @@ def put(self, *args, **kwargs):
     def patch(self, *args, **kwargs):
         """Perform an HTTP PATCH."""
         kwargs["timeout"] = kwargs.get("timeout", self._timeout)
+
+        if self._project is not None:
+            params = kwargs.get("params", {})
+            params["project"] = self._project
+            kwargs["params"] = params
+
         response = self.session.patch(self._api_endpoint, *args, **kwargs)
         self._assert_response(response, allowed_status_codes=(200, 202))
         return response
@@ -202,6 +230,12 @@ def patch(self, *args, **kwargs):
     def delete(self, *args, **kwargs):
         """Perform an HTTP delete."""
         kwargs["timeout"] = kwargs.get("timeout", self._timeout)
+
+        if self._project is not None:
+            params = kwargs.get("params", {})
+            params["project"] = self._project
+            kwargs["params"] = params
+
         response = self.session.delete(self._api_endpoint, *args, **kwargs)
         self._assert_response(response, allowed_status_codes=(200, 202))
         return response
@@ -277,7 +311,13 @@ class Client:
     """
 
     def __init__(
-        self, endpoint=None, version="1.0", cert=None, verify=True, timeout=None
+        self,
+        endpoint=None,
+        version="1.0",
+        cert=None,
+        verify=True,
+        timeout=None,
+        project=None,
     ):
         """Constructs a LXD client
 
@@ -293,9 +333,11 @@ def __init__(
         :param timeout: (optional) How long to wait for the server to send
             data before giving up, as a float, or a :ref:`(connect timeout,
             read timeout) <timeouts>` tuple.
+        :param project: (optional) Name of the LXD project to interact with.
 
         """
 
+        self.project = project
         self.cert = cert
         if endpoint is not None:
             if endpoint.startswith("/") and os.path.isfile(endpoint):
@@ -311,7 +353,9 @@ def __init__(
                     and os.path.exists(DEFAULT_CERTS.key)
                 ):
                     cert = DEFAULT_CERTS
-                self.api = _APINode(endpoint, cert=cert, verify=verify, timeout=timeout)
+                self.api = _APINode(
+                    endpoint, cert=cert, verify=verify, timeout=timeout, project=project
+                )
         else:
             if "LXD_DIR" in os.environ:
                 path = os.path.join(os.environ.get("LXD_DIR"), "unix.socket")
@@ -320,7 +364,7 @@ def __init__(
             else:
                 path = "/var/lib/lxd/unix.socket"
             endpoint = "http+unix://{}".format(parse.quote(path, safe=""))
-            self.api = _APINode(endpoint, timeout=timeout)
+            self.api = _APINode(endpoint, timeout=timeout, project=project)
         self.api = self.api[version]
 
         # Verify the connection is valid.
@@ -336,6 +380,13 @@ def __init__(
         ) as e:
             raise exceptions.ClientConnectionFailed(str(e))
 
+        if self.project and self.project != self.host_info["environment"].get(
+            "project", "default"
+        ):
+            raise exceptions.ClientConnectionFailed(
+                "Remote server doesn't handle projects"
+            )
+
         self.cluster = managers.ClusterManager(self)
         self.certificates = managers.CertificateManager(self)
         self.instances = managers.InstanceManager(self)


More information about the lxc-devel mailing list