Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove dependency on requests_unixsocket #583

Closed
simondeziel opened this issue Jun 7, 2024 · 4 comments · Fixed by #604
Closed

Remove dependency on requests_unixsocket #583

simondeziel opened this issue Jun 7, 2024 · 4 comments · Fixed by #604
Assignees

Comments

@simondeziel
Copy link
Member

The requests_unixsocket is abandoned and we have very little hope that msabramo/requests-unixsocket#72 will ever be merged.

cloud-init folks have found a way to talk to /dev/lxd/sock using requests (without using requests_unixsocket) to implement the LXD datasource. This could be taken as a source of inspiration for our replacement implementation.

@simondeziel
Copy link
Member Author

Related issues #579 and #581.

@simondeziel
Copy link
Member Author

Here's a toy PoC:

#!/usr/bin/python3

"""Basic interaction with the LXD API over the Unix socket."""

# Python implementation of:
# $ curl -s --unix /var/snap/lxd/common/lxd/unix.socket http://unix.socket/1.0 | jq -r '.metadata.environment'
#{
#  "addresses": [],
#  "architectures": [
#    "x86_64",
#    "i686"
#  ],
#...
#}

# Heavily inspired from snapd's api-client.py:
# https://github.com/snapcore/snapd/blob/master/tests/main/theme-install/api-client/bin/api-client.py

import http.client
import json
import socket
import sys


# This class is a subclass of http.client.HTTPConnection that connects to a Unix socket instead of a TCP socket.
class UnixSocketHTTPConnection(http.client.HTTPConnection):
    def __init__(self, socket_path):
        super().__init__("pylxd")
        self._socket_path = socket_path

    def connect(self):
        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        s.connect(self._socket_path)
        self.sock = s


# This function connects to the Unix socket and requests the environment part of the metadata returned by LXD.
# Returns the environment content of the metadata, or an empty string if an error occurs.
def main():
    # Try to connect to the Unix socket and request the environment part of the metadata returned by LXD.
    # If an exception occurs, print an error message and return an empty string.
    try:
        conn = UnixSocketHTTPConnection("/var/snap/lxd/common/lxd/unix.socket")
        conn.request("GET", "/1.0")
        response = conn.getresponse()
        body = response.read().decode()
    except FileNotFoundError:
        print("missing socket", file=sys.stderr)
        return ""
    except http.client.HTTPException as e:
        print("HTTP exception:", e, file=sys.stderr)
        return ""
    finally:
        conn.close()

    # If the response status is not 200, print an error message and return an empty string.
    if response.status != 200:
        print("HTTP error:", response.status, file=sys.stderr)
        return ""

    # If the response body is missing or empty, print an error message and return an empty string.
    if not body:
        print("Missing/empty body", file=sys.stderr)
        return ""

    # Try to parse the response body as JSON, and extract the environment part of the metadata returned by LXD.
    try:
        data = json.loads(body)
    except json.JSONDecodeError as e:
        print("JSON decode exception:", e, file=sys.stderr)
        return ""

    if "metadata" in data:
        return data["metadata"].get("environment", "")

    return ""


if __name__ == "__main__":
    print(main())

@C0rn3j
Copy link

C0rn3j commented Jul 7, 2024

@simondeziel
Copy link
Member Author

@C0rn3j indeed, thanks. We've considered this but we want to try if we can remove the dependency altogether first.

simondeziel added a commit that referenced this issue Oct 1, 2024
This includes implementation to connect to a Unix socket without
`requests_unixsocket`. This allows us to remove this dependency along
with the version restrictions for `urllib3` and `requests`;

Fixes #583
#600
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants