podman-py icon indicating copy to clipboard operation
podman-py copied to clipboard

Unix-Sockets connection not working

Open awildturtok opened this issue 2 years ago • 16 comments

Using podman-py we cannot connect to a local unix-socket. Irrespective of how we communicate the protocol, it will always end up as http.

The following does not work, it will end up making an http-request to http://%2frun%2fpodman.sock/v4.0.0/libpod/version instead of the unix-socket.

def podman_py():
    from podman import PodmanClient

    uri = "unix:///run/podman.sock"

    with PodmanClient(base_url=uri) as client:
        version = client.version()  # fails
        print("Release: ", version["Version"])
        print("Compatible API: ", version["ApiVersion"])
        print("Podman API: ", version["Components"][0]["Details"]["APIVersion"], "\n")

For comparison, the following, manual connection to the socket works:

def podman_requests_unixsocket():
    import requests_unixsocket

    url = "http+unix://%2frun%2fpodman.sock/v4.0.0/libpod/version"

    with requests_unixsocket.Session() as session:
        response = session.get(url)
        response.raise_for_status()
        version = json.loads(response.text)
        print("Release: ", version["Version"])
        print("Compatible API: ", version["ApiVersion"])
        print("Podman API: ", version["Components"][0]["Details"]["APIVersion"], "\n")

My suspicion is that we are doing something wrong, or that something is lost in translation when hard-coding the protocol to http and then mapping to UDSAdapter down the line.


We made some manual changes to podman-py that seem to do the trick (although they look wrong to me):

podman/api/uds.py#108:

    # Map supported schemes to Pool Classes
    _pool_classes_by_scheme = {
        "http": UDSConnectionPool,
        "http+unix": UDSConnectionPool,
        "http+ssh": UDSConnectionPool,
    }

    # Map supported schemes to Pool Key index generator
    _key_fn_by_scheme = {
        "http": functools.partial(_key_normalizer, _PoolKey),
        "http+unix": functools.partial(_key_normalizer, _PoolKey),
        "http+ssh": functools.partial(_key_normalizer, _PoolKey),
    }

podman/api/client.py#126

        if self.base_url.scheme == "http+unix":
            self.mount("http+unix://", UDSAdapter(self.base_url.geturl(), **adapter_kwargs))

podman/api/client.py#396

        uri = urllib.parse.ParseResult(
            "http+unix",
            self.base_url.netloc,
            urllib.parse.urljoin(path_prefix, path),
            self.base_url.params,
            self.base_url.query,
            self.base_url.fragment,
        )

We are using version 4.0.0

awildturtok avatar Jul 21 '22 10:07 awildturtok

Hey,

I think you are passing wrong url. In podman socket socket is located under /run/podman/podman.sock by default. You are probably used to docker where socket was located under /run/docker.sock

Python 3.6.8 (default, Jan 14 2022, 11:04:20)
[GCC 8.5.0 20210514 (Red Hat 8.5.0-7)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def podman_py(uri):
...     from podman import PodmanClient
...     with PodmanClient(base_url=uri) as client:
...         version = client.version()  # fails
...         print("Release: ", version["Version"])
...         print("Compatible API: ", version["ApiVersion"])
...         print("Podman API: ", version["Components"][0]["Details"]["APIVersion"], "\n")
...
>>> for uri in ["unix:///run/podman.sock", "unix:///run/podman/podman.sock"]:
...     try:
...         print(podman_py(uri=uri))
...     except:
...         print(f'uri {uri} failed')
...
uri unix:///run/podman.sock failed
Release:  4.0.2
Compatible API:  1.40
Podman API:  4.0.2

msisj avatar Jul 29 '22 13:07 msisj

@msisj the socket is mounted there by us. And as I demonstrate in the lower snippet, acessing the socket does work, just not with podman-py.

awildturtok avatar Aug 01 '22 15:08 awildturtok

I am hitting some similar issues. The module was working with the following uri - f"unix:///run/user/{os.getuid()}/podman/podman.sock until I run the following command: sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER && podman system migrate. The usermod command was used to solve an image build failure.

lmilbaum avatar Aug 31 '22 09:08 lmilbaum

If you run podman natively does it work?

rhatdan avatar Aug 31 '22 10:08 rhatdan

If you run podman natively does it work?

Nop. It stopped working as well. Is there a way to restore the settings before the usermod command?

lmilbaum avatar Aug 31 '22 10:08 lmilbaum

@rhatdan I was able to revert the change such that podman cli returned working. The api is not. Hitting the error requests.exceptions.ConnectionError: ('Connection aborted.', APIError("Unable to make connection to UDS '/run/user/114164/podman/podman.sock'"))

lmilbaum avatar Aug 31 '22 11:08 lmilbaum

@cdoern PTAL

rhatdan avatar Sep 06 '22 18:09 rhatdan

@awildturtok can you please paste the output you get when this fails? also, please run systemctl start podman to ensure the socket it listening and that the system service is using this socket.

This most likely is not on our end, as I just fresh installed podman-py 4.2 and ran the test code, and it succeeded. I would assume the custom mounting of the socket is not right.

cdoern avatar Sep 09 '22 15:09 cdoern

Just a question here... I was trying to embed this is a container to deal with image registry checking part... But it's really necessary to have the socket available to do this part? I am not following right the stuff being said about Portman. Is it was not said that podman was daemonless? It the socket is not for the API Daemon, it's for what?

ryukinix avatar Apr 27 '23 15:04 ryukinix

podman runs well without any daemon or service. If you want to talk to the remote API via podman-py, docker-py, docker-compose ... Then we need to have a service listening for incoming connections. This is also provided via a Podman systemd socket activated service. Which will handle connections and shuts down within 10 seconds of the last connection. If you want to call this a daemon, then fine.

rhatdan avatar Apr 27 '23 16:04 rhatdan

My main intent it's to create a mechanism to getting a registry image so I can validate if the image exists with the respective tag...

That is a embedded application deployed in a k8s without access to a docker daemon, so I thought about using podman, but I had problems about the socket.

I receive for instance: gcr.io/namespace/image:latest

I want to check if that exists or not.

ryukinix avatar Apr 28 '23 00:04 ryukinix

So you want to pull the image into the container, or are you looking to see if k8s has pulled the image?

rhatdan avatar Apr 28 '23 14:04 rhatdan

Neither of that, I only want to validate if the given remote repository image exists, not necessarily I need to pull and download it...

I could just use http... But checking directly via http get can be cumbersome if there is multiple possible docker registries (potential places to check: on-premisse registries, gcr.io etc)

So the whole OCI container engineer is not necessary for this application.

Cordialmente, Manoel Vilela.

Em sex., 28 de abr. de 2023 11:23, Daniel J Walsh @.***> escreveu:

So you want to pull the image into the container, or are you looking to see if k8s has pulled the image?

— Reply to this email directly, view it on GitHub https://github.com/containers/podman-py/issues/188#issuecomment-1527648403, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB2J57RVERM3TDY5VIHQU2TXDPHEJANCNFSM54HFK54A . You are receiving this because you commented.Message ID: @.***>

ryukinix avatar Apr 29 '23 00:04 ryukinix

Why not use skopeo inspect

rhatdan avatar Apr 29 '23 10:04 rhatdan

Thank you for sharing skopeo, that's the type of utility I was looking for. Unfortunately it's written in Go and make integration a little bit worse in the kind of application will be embedded with it.

It would be nice if skopeo provided a python client library wrapper for this.

Sorry for bothering podman-py with this.

cc @luizmanke

Cordialmente, Manoel Vilela.

Em sáb., 29 de abr. de 2023 07:46, Daniel J Walsh @.***> escreveu:

Why not use skopeo inspect

— Reply to this email directly, view it on GitHub https://github.com/containers/podman-py/issues/188#issuecomment-1528755936, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB2J57TRUJRRG3QRQIZU5XTXDTWQNANCNFSM54HFK54A . You are receiving this because you commented.Message ID: @.***>

ryukinix avatar Apr 29 '23 12:04 ryukinix

I'm doing something very similar @ryukinix, my extra pain point is that I'm doing it from within a docker container. Anyhow you need to start the podman service:

# this will run until killed
podman system service --time=0 unix:///tmp/podman.sock &

then within your python code

import podman

uri="unix:///tmp/podman.sock"
client = podman.PodmanClient(base_url=uri)

docker_image = "registry.hub.docker.com/library/busybox:latest"

manifest = client.manifests.get(docker_image)
if manifest is None:
  print("image does not exist in registry")
else:
  print("ok!")

Note that I'm having issues with the subuids/subguids, but to check this image, you should be ok without anything set.

mkst avatar Sep 15 '23 07:09 mkst