GithubHelp home page GithubHelp logo

containers / podman-py Goto Github PK

View Code? Open in Web Editor NEW
222.0 12.0 81.0 848 KB

Python bindings for Podman's RESTful API

License: Apache License 2.0

Python 98.66% Makefile 0.70% Shell 0.65%
podman python libpod

podman-py's Introduction

podman-py

Build Status

This python package is a library of bindings to use the RESTful API of Podman. It is currently under development and contributors are welcome!

Dependencies

Example usage

"""Demonstrate PodmanClient."""
import json
from podman import PodmanClient

# Provide a URI path for the libpod service.  In libpod, the URI can be a unix
# domain socket(UDS) or TCP.  The TCP connection has not been implemented in this
# package yet.

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

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

    # get all images
    for image in client.images.list():
        print(image, image.id, "\n")

    # find all containers
    for container in client.containers.list():
        first_name = container['Names'][0]
        container = client.containers.get(first_name)
        print(container, container.id, "\n")

        # available fields
        print(sorted(container.attrs.keys()))

    print(json.dumps(client.df(), indent=4))

Contributing

See CONTRIBUTING.md

podman-py's People

Contributors

apozsuse avatar baude avatar bmarlow avatar bors[bot] avatar cdoern avatar cevich avatar chnrxn avatar dcermak avatar ericpershey avatar erikbgithub avatar gotmax23 avatar jonathanunderwood avatar jwhonce avatar kajinamit avatar lsm5 avatar mgorny avatar milanbalazs avatar mrbazzan avatar msisj avatar mwhahaha avatar openshift-ci[bot] avatar openshift-merge-bot[bot] avatar openshift-merge-robot avatar razcrimson avatar renovate[bot] avatar rhatdan avatar sshnaidm avatar timc avatar tomsweeneyredhat avatar umohnani8 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

podman-py's Issues

In Py3.7 cannot create container with volumes

Calling client.container.create(image_id, ..., volumes={'/foo': '/bar'}) raises ValueError: too many values to unpack (expected 2)

The line in question is in podman/domain/containers_create.py line 463, in _render_payload:

for item in args.pop("volumes", dict()):
    key, value = item

In this case it looks like item just refers to a key in the dict. Would something like args.pop("volumes", dict()).items() be better? I don't have much experience with pull requests here on GitHub, so not sure the best way to handle this.

APIError with Podman 3.4.4

Hi !

I just install a fresh Podman 3.4.4 on my Ubuntu 22.04 system:

host:
  arch: amd64
  buildahVersion: 1.23.1
  cgroupControllers:
  - memory
  - pids
  cgroupManager: systemd
  cgroupVersion: v2
  conmon:
    package: 'conmon: /usr/bin/conmon'
    path: /usr/bin/conmon
    version: 'conmon version 2.0.25, commit: unknown'
  cpus: 4
  distribution:
    codename: jammy
    distribution: ubuntu
    version: "22.04"
  eventLogger: journald
  hostname: XPS13-9333
  idMappings:
    gidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 100000
      size: 65536
    uidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 100000
      size: 65536
  kernel: 5.15.0-30-generic
  linkmode: dynamic
  logDriver: journald
  memFree: 168615936
  memTotal: 7837949952
  ociRuntime:
    name: crun
    package: 'crun: /usr/bin/crun'
    path: /usr/bin/crun
    version: |-
      crun version 0.17
      commit: 0e9229ae34caaebcb86f1fde18de3acaf18c6d9a
      spec: 1.0.0
      +SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +YAJL
  os: linux
  remoteSocket:
    path: /run/user/1000/podman/podman.sock
  security:
    apparmorEnabled: false
    capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT
    rootless: true
    seccompEnabled: true
    seccompProfilePath: /usr/share/containers/seccomp.json
    selinuxEnabled: false
  serviceIsRemote: false
  slirp4netns:
    executable: /usr/bin/slirp4netns
    package: 'slirp4netns: /usr/bin/slirp4netns'
    version: |-
      slirp4netns version 1.0.1
      commit: 6a7b16babc95b6a3056b33fb45b74a6f62262dd4
      libslirp: 4.6.1
  swapFree: 7746674688
  swapTotal: 8082419712
  uptime: 67h 59m 53.68s (Approximately 2.79 days)
plugins:
  log:
  - k8s-file
  - none
  - journald
  network:
  - bridge
  - macvlan
  volume:
  - local
registries:
  search:
  - registry.access.redhat.com
  - registry.fedoraproject.org
  - docker.io
store:
  configFile: /home/nicolargo/.config/containers/storage.conf
  containerStore:
    number: 1
    paused: 0
    running: 1
    stopped: 0
  graphDriverName: overlay
  graphOptions: {}
  graphRoot: /home/nicolargo/.local/share/containers/storage
  graphStatus:
    Backing Filesystem: extfs
    Native Overlay Diff: "true"
    Supports d_type: "true"
    Using metacopy: "false"
  imageStore:
    number: 1
  runRoot: /run/user/1000/containers
  volumePath: /home/nicolargo/.local/share/containers/storage/volumes
version:
  APIVersion: 3.4.4
  Built: 0
  BuiltTime: Thu Jan  1 01:00:00 1970
  GitCommit: ""
  GoVersion: go1.17.3
  OsArch: linux/amd64
  Version: 3.4.4

When i try to connect to Podman with Podman-py 4.0.0 version :

$ python
>>> from podman import PodmanClient
>>> uri = "unix:///run/user/1000/podman/podman.sock"
>>> PodmanClient(base_url=uri).version()

I have the following error:

Traceback (most recent call last):
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/api/uds.py", line 43, in connect
    super().connect(netloc)
FileNotFoundError: [Errno 2] No such file or directory

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 703, in urlopen
    httplib_response = self._make_request(
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 398, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/lib/python3.10/http/client.py", line 1282, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1328, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1277, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1037, in _send_output
    self.send(msg)
  File "/usr/lib/python3.10/http/client.py", line 975, in send
    self.connect()
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/api/uds.py", line 88, in connect
    sock.connect()
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/api/uds.py", line 45, in connect
    raise APIError(f"Unable to make connection to UDS '{netloc}'") from e
podman.errors.exceptions.APIError: Unable to make connection to UDS '/run/user/1000/podman/podman.sock'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/requests/adapters.py", line 440, in send
    resp = conn.urlopen(
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 785, in urlopen
    retries = retries.increment(
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/urllib3/util/retry.py", line 550, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/urllib3/packages/six.py", line 769, in reraise
    raise value.with_traceback(tb)
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 703, in urlopen
    httplib_response = self._make_request(
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 398, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/lib/python3.10/http/client.py", line 1282, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1328, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1277, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1037, in _send_output
    self.send(msg)
  File "/usr/lib/python3.10/http/client.py", line 975, in send
    self.connect()
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/api/uds.py", line 88, in connect
    sock.connect()
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/api/uds.py", line 45, in connect
    raise APIError(f"Unable to make connection to UDS '{netloc}'") from e
urllib3.exceptions.ProtocolError: ('Connection aborted.', APIError("Unable to make connection to UDS '/run/user/1000/podman/podman.sock'"))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/api/client.py", line 407, in _request
    self.request(
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/requests/sessions.py", line 529, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/requests/sessions.py", line 645, in send
    r = adapter.send(request, **kwargs)
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/requests/adapters.py", line 501, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', APIError("Unable to make connection to UDS '/run/user/1000/podman/podman.sock'"))

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/client.py", line 200, in version
    return self.system.version(**kwargs)
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/domain/system.py", line 70, in version
    response = self.client.get("/version")
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/api/client.py", line 239, in get
    return self._request(
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/api/client.py", line 418, in _request
    raise APIError(uri.geturl(), explanation=f"{method.upper()} operation failed") from e
podman.errors.exceptions.APIError: http://%2Frun%2Fuser%2F1000%2Fpodman%2Fpodman.sock/v4.0.0/libpod/version (GET operation failed)

Any idea ?

Cannot specify workdir when starting container

Running podman version 2.2.1, with podman-py version 3.1.2.4 (the latest at the time of writing this)

When using the working dir kwarg here it doesn't seem to have any effect on the container

After going in and changing working_dir to work_dir here to match the podman docs the flag started working. I think this is just a typo

Inconsistent docstring format used throughout

The docstring format used throughout the project is inconsistent. Sometimes they are reminiscent of Google docstrings, sometimes they look like numpy docstrings. A decision needs to be made and documented on the required docstring format to enable contributors to improve the docstrings.

PEP8 style guide

As a python developer and a big fan of podman, I might find this package useful in order to automate some container processes. But now, I see there's a lack of features and I think this is a perfect moment to improve code quality. PEP8 is the official style guide for python and this library could follow those principles in a more strictly way.

i. e.

Before PEP8

def __init__(self, url, base="/v1.24/libpod", *args,
    **kwargs):  # pylint: disable-msg=W1113

After PEP8

def __init__(
    self, url, base="/v1.24/libpod", *args, **kwargs
):  # pylint: disable-msg=W1113

can't specify a volume via a host path

According to the documentation listed here https://github.com/containers/podman-py/blob/main/podman/domain/containers_create.py

            volumes (Dict[str, Dict[str, str]]): A dictionary to configure volumes mounted inside
                the container. The key is either the host path or a volume name, and the value is
                a dictionary with the keys:
                - bind: The path to mount the volume inside the container
                - mode: Either rw to mount the volume read/write, or ro to mount it read-only.
                For example:
                    {'/home/user1/': {'bind': '/mnt/vol2', 'mode': 'rw'},
                     '/var/www': {'bind': '/mnt/vol1', 'mode': 'ro'}}

...a dictionary is needed to configure volumes inside the container.

Ok, so I'm literally using the same example to create a container.

client.containers.create(image=podman_image_name, name=podman_container_name, volumes={'/home/user1/': {'bind': '/mnt/vol2', 'mode': 'rw'}}

However, I'm met with the following error:

  File "/home/user1/Desktop/podman-clamav-el6/./script-podman.py", line 167, in <module>
    ensure_container_exists_and_running()
  File "/home/user1/Desktop/podman-clamav-el6/./script-podman.py", line 119, in ensure_container_exists_and_running
    run_container()
  File "/home/user1/Desktop/podman-clamav-el6/./script-podman.py", line 139, in run_container
    client.containers.create(image=podman_image_name, name=podman_container_name, volumes={'/home/user1/': {'bind': '/mnt/vol2', 'mode': 'rw'}})    
  File "/usr/lib/python3.10/site-packages/podman/domain/containers_create.py", line 224, in create
    response.raise_for_status(not_found=ImageNotFound)
  File "/usr/lib/python3.10/site-packages/podman/api/client.py", line 65, in raise_for_status
    raise APIError(cause, response=self._response, explanation=message)
podman.errors.exceptions.APIError: 500 Server Error: Internal Server Error (error creating named volume "/home/user1/": error running volume create option: names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*: invalid argument)

It's trying to create a named volume vs using the host path --even though the documentation clearly states The key is either the host path or a volume name

This was MUCH easier with docker-py where you could just provide a list of mounts.

I'll dig through the code later, but in the meantime any help would be appreciated.

why the `__ALL__` definitions ?

just want to outline that

  • __ALL__ should be spelled __all__, like all other special names
  • plus, and more to the point, there are lighter conventions to just rely on the public / _private naming convention, which seems to be in place already since _report_not_found follows the _private pattern

So I just wanted to make sure that it was mandatory to have these defined for some higher level reason, like it's a redhat policy or something

Otherwise I'd suggest to simply drop it, as it serves no visible purpose (evidence of that being that it is currently misspelled), and just adds possibility for error

Podman pods.list() returns truncated IDs that can not be used by pods.get()

$ podman create pod --name mypod
$ cat podman-pods.py
import podman
client=podman.PodmanClient()
for i in client.pods.list():
    print(i)
    print(help(client.pods.get(pod_id=i)))
$ python podman-images.py
<Pod: 116291543d>
Traceback (most recent call last):
  File "/home/dwalsh/go/src/github.com/containers/common/podman-images.py", line 5, in <module>
    print(help(client.pods.get(pod_id=i)))
  File "/usr/lib/python3.10/site-packages/podman/domain/pods_manager.py", line 56, in get
    response.raise_for_status()
  File "/usr/lib/python3.10/site-packages/podman/api/client.py", line 64, in raise_for_status
    raise not_found(cause, response=self._response, explanation=message)
podman.errors.exceptions.NotFound: 404 Client Error: Not Found (no pod with name or ID <Pod: 116291543d> found: no such pod)

I think there might be two bugs here.

  1. List, should not truncate the IDs returned.
  2. Podman pod.get() should be able to handle truncated IDs.

Context path error during image build

According to image.build, path references the build context directory. This works for ".", but not for subdirectories.

Given the following directory tree:

src
├── context_dir
│   ├── Dockerfile
│   └── <further files in context>
└── example.py

and the following code:

client.images.build(
  path="context_dir/",
  dockerfile="context_dir/Dockerfile",
)

results in:
Build Error( "stat /var/tmp/libpod_builder2054394681/build/context_dir/Dockerfile: no such file or directory

Versions:

"Version": "3.4.2",
"ApiVersion": "1.40",
"MinAPIVersion": "1.24",

My Workaround:

os.chdir('context_dir')
clientimages.build(
  path=".",
  dockerfile="Dockerfile",
)

Unix-Sockets connection not working

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

naming

I can see functions

  • system.get_info() that uses libpod's path /info
  • system.show_disk_usage() linked to /system/df

should we not try to define some kind of mapping between all these names ?

Socket Broken Pipe

I tried running the code that exists in podman/api_connection.py and facing a Socket broken pipe issue.
Below is the stack trace for the error observed. Is there any workaround to fix this?
Traceback (most recent call last):
File "", line 1, in
File "", line 35, in request
File "/usr/lib/python3.8/http/client.py", line 1255, in request
self._send_request(method, url, body, headers, encode_chunked)
File "/usr/lib/python3.8/http/client.py", line 1301, in _send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/usr/lib/python3.8/http/client.py", line 1250, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/lib/python3.8/http/client.py", line 1010, in _send_output
self.send(msg)
File "/usr/lib/python3.8/http/client.py", line 971, in send
self.sock.sendall(data)
BrokenPipeError: [Errno 32] Broken pipe

Error on commit container

There is an error in the podman/domain/containers.py file trying to commit a container (Line 115):

Traceback (most recent call last):
File "main.py", line 24, in
container.commit(repository=f"localhost/{container.name}", tag="latest")
File "/root/dev/podman-bk/podman-bk/lib64/python3.6/site-packages/podman/domain/containers.py", line 115, in commit
return ImagesManager(client=self.client).get(body["ID"])
KeyError: 'ID'

The Key 'ID' does not exist at least in my podman version. The correct key is 'Id'. Example:

{'Id': '106ede7ca43b70673cf41716bbeddd73a7e1efbe9316c5a69340c6df5a395cca'}

Podman packages versions:

podman-docker-3.4.2-9.module+el8.5.0+735+2f243138.noarch
podman-remote-3.4.2-9.module+el8.5.0+735+2f243138.x86_64
podman-3.4.2-9.module+el8.5.0+735+2f243138.x86_64
podman-catatonit-3.4.2-9.module+el8.5.0+735+2f243138.x86_64

Image can not have registry port in name

If image has registry with port number the Container.image method is going to raise podman.errors.exceptions.ImageNotFound due to invalid split.

Example :

[root@host ~]# podman ps -a
CONTAINER ID  IMAGE                    COMMAND     CREATED        STATUS      PORTS       NAMES
6c274c264cb5  registry:443/a/b/c:test  /bin/bash   3 minutes ago  Created                 the_test
[root@cmep ~]# python3
Python 3.6.8 (default, Mar 18 2021, 08:58:41)
[GCC 8.4.1 20200928 (Red Hat 8.4.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import podman
>>> client = podman.PodmanClient(base_url='unix:///run/podman/podman.sock', timeout=300)
>>> client.containers.list(all=True)[0].image
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/site-packages/podman/domain/containers.py", line 39, in image
    return ImagesManager(client=self.client).get(image_id)
  File "/usr/lib/python3.6/site-packages/podman/domain/images_manager.py", line 74, in get
    response.raise_for_status(not_found=ImageNotFound)
  File "/usr/lib/python3.6/site-packages/podman/api/client.py", line 64, in raise_for_status
    raise not_found(cause, response=self._response, explanation=message)
podman.errors.exceptions.ImageNotFound: 404 Client Error: Not Found (failed to find image 443/a/b/c: 443/a/b/c: image not known)

Using sockets equal to client <-> server connection?

Hi,

I used docker containers for some time, but didn´t bother the underlying technicalities. I came accross Podman and liked some of its underlying differing techniques. I hope I won´t make a complete fool out of me for this issue...

As I understand it, one huge drawback of docker is, that it uses a client <-> server structure. From a security point, this implies that it is hard to follow who issued commands: A docker command from the commandline is sent to the server and the server creates a new container. Since the server creates the container, the system can´t audit who issued the former command on the commandline and hence we have a security problem. Podman in contrast does not have this client <-> server structure. The command issued on the commandline directly creates the container; additionaly we don´t need any daemon running in the background. This might be an oversimplified summary of what I read in articles about differences of docker and Podman.

If I understand the code here correct, this project will use an ApiConnector that communicates via sockets with another program. Latter program will create containers, when the python programm wants it to. But isn´t this again a server <-> client communication, where we need a program listening on the socket?

I do understand, that one needs a client <-> server communication, when one wants to communicate with a remote host. But when a python application wants to run a container on the same system, wouldn´t it be more "safe", to execute the podman command as a subprocess?

possibly incorrect documentation for `CreateMixin` args

It seems that volumes is document as a Dict[str, Dict[str, str]] but the code that utilizes it is expecting a List[Tuple[str, Dict[str, str]]] as python doesn't support unpacking dictionaries directly.

volumes (Dict[str, Dict[str, str]]): A dictionary to configure volumes mounted inside
the container. The key is either the host path or a volume name, and the value is
a dictionary with the keys:
- bind: The path to mount the volume inside the container
- mode: Either rw to mount the volume read/write, or ro to mount it read-only.
For example:
{'/home/user1/': {'bind': '/mnt/vol2', 'mode': 'rw'},
'/var/www': {'bind': '/mnt/vol1', 'mode': 'ro'}}

for item in args.pop("volumes", dict()):
key, value = item
volume = {
"Name": key,
"Dest": value["bind"],
"Options": [value["mode"]],
}
params["volumes"].append(volume)

>>> x = {"one": {"two": "test"}}
>>> y, z = x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 2, got 1)
>>> a = ("one", {"two": "test"})
>>> y, z = a
>>> y
'one'
>>> z
{'two': 'test'}

containers/create needs parameter

According to the swagger documentation and the implementation of Podman 2.0 REST API the container name must a query parameter, and container data the parameters.
Currently only container data is send, not the name which results in HTTP error 500.

I've tested with CURL:
curl --unix-socket <> -X POST "http://d/v2.0.0/containers/create?name=<name>" -H "Content-Type: application/json" -d "{\"Image\":\"alpine\"}" which works.
I will be happy to fix it, but I am having a hard time to see how that should be done using the current http lib, and the POST abstractions done.

Versioning Issue (perhaps already resolved)

@jwhonce I noticed the latest release tag follows semver, but the older tags didn't. Just making sure we'll be following semver going forward as changing formats also ends up changing the format of the release tarballs, which can cause problems with the automated rpm builds.

Running new container fails to pull missing image

Try this Python script that runs a container from an image that has not been pulled yet:

import podman

image = 'docker.io/library/alpine'

with podman.PodmanClient() as client:
    # client.images.pull(image)
    out = client.containers.run(image, ['echo', 'hello world'], remove=True)
    print(out)

It fails with:

Traceback (most recent call last):
  File "/home/ewie/test.py", line 7, in <module>
    out = client.containers.run(image, ['echo', 'hello world'], remove=True)
  File "/home/ewie/.venv/lib/python3.10/site-packages/podman/domain/containers_run.py", line 61, in run
    container = self.create(image=image, command=command, **kwargs)
  File "/home/ewie/.venv/lib/python3.10/site-packages/podman/domain/containers_create.py", line 274, in create
    response.raise_for_status(not_found=ImageNotFound)
  File "/home/ewie/.venv/lib/python3.10/site-packages/podman/api/client.py", line 63, in raise_for_status
    raise APIError(cause, response=self._response, explanation=message)
podman.errors.exceptions.APIError: 500 Server Error: Internal Server Error (docker.io/library/alpine: image not known)

Uncomment line 6 to manually pull the image and the container runs as expected:

b'hello world\n'

I see that images should be pulled automatically (like podman run on the command line) if the API responds with 404 Not Found:

except ImageNotFound:
self.client.images.pull(image, platform=kwargs.get("platform"))

But the stack trace above shows that the API responds with 500 Server Error.

About my system:

  • podman-py: 2f8b45a
  • Python: 3.10.9
  • Podman:
    Client:       Podman Engine
    Version:      4.4.0
    API Version:  4.4.0
    Go Version:   go1.20
    Git Commit:   3443f453e28169a88848f90a7ce3137fc4a4bebf-dirty
    Built:        Sat Feb  4 00:28:28 2023
    OS/Arch:      linux/amd64
    
  • OS:
    Linux desktop 6.1.9-arch1-1 #1 SMP PREEMPT_DYNAMIC Wed, 01 Feb 2023 17:07:39 +0000 x86_64 GNU/Linux
    

Documentation?

Hi,

I've been looking around a little bit for solid documentation for this project, as I plan to utilize it. I noticed there's no ReadTheDocs site, and mkdocs doesn't build anything except for a 404 page. I was curious if there is documentation hosted here, on GitHub Pages, on RTD, or others, or if there are plans do to so?

Thanks in advance!

PodmanClient fails with base_url defined: got multiple values for argument 'base_url'

By running the simple example it fails (installed from git master):

>>> from podman import PodmanClient
>>> uri1 = "unix:///run/user/1000/podman/podman.sock"
>>> with PodmanClient(uri1) as client:
...     version = client.version()
16:19:16.85 >>> Call to PodmanClient.__init__ in File "/home/sshnaidm/sources/podman-py/podman/client.py", line 38
16:19:16.85 .......... self = <podman.client.PodmanClient object at 0x7fb1bc99dca0>
16:19:16.85 .......... args = ('unix:///run/user/1000/podman/podman.sock',)
16:19:16.85 .......... len(args) = 1
16:19:16.85 .......... kwargs = {}
16:19:16.85 .......... __class__ = <class 'podman.client.PodmanClient'>
16:19:16.85   38 |     def __init__(self, *args, **kwargs) -> None:
16:19:16.85   63 |         super().__init__()
16:19:16.85   64 |         config = PodmanConfig()
16:19:16.85 .............. config = <podman.domain.config.PodmanConfig object at 0x7fb1bc99dc10>
16:19:16.85   66 |         api_kwargs = kwargs.copy()
16:19:16.85 .............. api_kwargs = {}
16:19:16.85   68 |         if "connection" in api_kwargs:
16:19:16.85   74 |         elif "base_url" not in api_kwargs:
16:19:16.86   75 |             path = str(
16:19:16.86   76 |                 Path(xdg.BaseDirectory.get_runtime_dir(strict=False)) / "podman" / "podman.sock"
16:19:16.86   75 |             path = str(
16:19:16.86 .................. path = '/run/user/1000/podman/podman.sock'
16:19:16.86   78 |             api_kwargs["base_url"] = "http+unix://" + path
16:19:16.86 .................. api_kwargs = {'base_url': 'http+unix:///run/user/1000/podman/podman.sock'}
16:19:16.86 .................. len(api_kwargs) = 1
16:19:16.86   79 |         self.api = APIClient(*args, **api_kwargs)
16:19:16.86 !!! TypeError: __init__() got multiple values for argument 'base_url'
16:19:16.86 !!! When calling: APIClient(*args, **api_kwargs)
16:19:16.86 !!! Call ended by exception
2021-05-10 16:19:16.862 | ERROR    | __main__:<module>:1 - An error has been caught in function '<module>', process 'MainProcess' (281384), thread 'MainThread' (140403397965632):
Traceback (most recent call last):

  File "/home/sshnaidm/venvs/py2/lib/python2.7/site-packages/dreampielib/data/subp_main.py", line 44, in <module>
    main()
    └ <function main at 0x7fb2292f4670>

  Fi
Traceback (most recent call last):
  File "<pyshell#5>", line 2, in <module>
    version = client.version()
  File "/home/sshnaidm/sources/podman-py/podman/client.py", line 203, in version
    def version(self, *args, **kwargs):  # pylint: disable=missing-function-docstring
  File "/usr/lib64/python3.9/functools.py", line 969, in __get__
    val = self.func(instance)
  File "/home/sshnaidm/sources/podman-py/podman/client.py", line 174, in system
    @cached_property
AttributeError: 'PodmanClient' object has no attribute 'api'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#5>", line 2, in <module>
    version = client.version()
  File "/home/sshnaidm/sources/podman-py/podman/client.py", line 85, in __exit__
  File "/home/sshnaidm/sources/podman-py/podman/client.py", line 209, in close
    def close(self):
AttributeError: 'PodmanClient' object has no attribute 'api'
le "/home/sshnaidm/venvs/py2/lib/python2.7/site-packages/dreampielib/data/subp_main.py", line 41, in main
    subprocess_main(port)
    │               └ 10020<function main at 0x7fb22901d790>

  File "/home/sshnaidm/venvs/py2/lib/python2.7/site-packages/dreampielib/data/subp-py3/dreampielib/subprocess/__init__.py", line 1060, in main
    _subp = Subprocess(port)
            │          └ 10020<class 'dreampielib.subprocess.Subprocess'>

  File "/home/sshnaidm/venvs/py2/lib/python2.7/site-packages/dreampielib/data/subp-py3/dreampielib/subprocess/__init__.py", line 233, in __init__
    self.loop()
    │    └ <function Subprocess.loop at 0x7fb2290184c0><dreampielib.subprocess.Subprocess object at 0x7fb229304460>

  File "/home/sshnaidm/venvs/py2/lib/python2.7/site-packages/dreampielib/data/subp-py3/dreampielib/subprocess/__init__.py", line 245, in loop
    for obj in r:
        │      └ <generator object Subprocess.execute at 0x7fb1bc994cf0>
        └ (True, None)

  File "/home/sshnaidm/venvs/py2/lib/python2.7/site-packages/dreampielib/data/subp-py3/dreampielib/subprocess/__init__.py", line 433, in execute
    exec(codeob, self.locs)
         │       │    └ {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': None, '__spec__': None, '__builtins__': {'__name...
         │       └ <dreampielib.subprocess.Subprocess object at 0x7fb229304460><code object <module> at 0x7fb2284ad030, file "<pyshell#5>", line 1>

> File "<pyshell#5>", line 1, in <module>
    with PodmanClient(uri1) as client:
         │            │        └ <podman.client.PodmanClient object at 0x7fb229088c70>
         │            └ 'unix:///run/user/1000/podman/podman.sock'<class 'podman.client.PodmanClient'>
  File "/home/sshnaidm/.local/lib/python3.9/site-packages/snoop/tracer.py", line 170, in simple_wrapper
    return function(*args, **kwargs)
           │         │       └ {}
           │         └ (<podman.client.PodmanClient object at 0x7fb1bc99dca0>, 'unix:///run/user/1000/podman/podman.sock')
           └ <function PodmanClient.__init__ at 0x7fb1bc984040>

  File "/home/sshnaidm/sources/podman-py/podman/client.py", line 79, in __init__
    self.api = APIClient(*args, **api_kwargs)
    │          │          │       └ {'base_url': 'http+unix:///run/user/1000/podman/podman.sock'}
    │          │          └ ('unix:///run/user/1000/podman/podman.sock',)
    │          └ <class 'podman.api.client.APIClient'><podman.client.PodmanClient object at 0x7fb1bc99dca0>

TypeError: __init__() got multiple values for argument 'base_url'

Error handling in api.request

Hello, and thank you for making this package!

I noticed that in the api.request method, the error message returned by the server is not captured. For example we might get:

podman.errors.InternalServerError: Request POST:/v2.0.0/libpod/containers/create failed: Server got itself in trouble

Instead of:

Decode(): json: cannot unmarshal string into Go struct field SpecGenerator.cni_networks of type []string

Is that on your roadmap, or would you be open to a PR adding that handling?

No such file or directory error when building image

Have met a problem during building an image through podman-py:

File "/usr/local/lib/python3.8/site-packages/podman/domain/images_build.py", line 89, in build
    params["dockerfile"] = api.prepare_containerfile(kwargs["path"], params["dockerfile"])

File "/usr/local/lib/python3.8/site-packages/podman/api/tar_utils.py", line 50, in prepare_containerfile
    shutil.copy2(dockerfile_path, proxy_path, follow_symlinks=False)

File "/usr/lib64/python3.8/shutil.py", line 435, in copy2
    copyfile(src, dst, follow_symlinks=follow_symlinks)

File "/usr/lib64/python3.8/shutil.py", line 264, in copyfile
    with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:

FileNotFoundError: [Errno 2] No such file or directory: '.containerfile.7482d90f40a649bde91353e5326d5a698053219c'

It appears if path parameter for images.build is set, but dockerfile isn't.

Looked a bit into podman-py code and found probable cause of this issue in podman-py/podman/api/tar_utils/prepare_containerfile:

proxy_path = anchor_path / f".containerfile.{random.getrandbits(160):x}"
shutil.copy2(dockerfile_path, proxy_path, follow_symlinks=False)
return proxy_path.name

It seems, that between creating path and copying - there should be creation of temporary file.

Stream option for pulling images

Hey,

Didn't know where to write it, because the change is needed between podman-py and podman REST Api, but as I'm not that familiar with podman REST Api source (honestly podman project is so complex I can't find definitions of the REST endpoints there :|) I decided to write here.

I'm wondering whether stream option could be a part of podman-py at some point.
In docker-py there was such functionality (stream (bool) – Stream the output as a generator. Make sure to consume the generator, otherwise pull might get cancelled.)
Thanks to it, it was possible to show progress of pulling images to the user, which is a cool and useful feature (note that regular podman pull does it by default).

The information about progress is actually somewhat there.
To prove that I've added one simple print(body) here.
Which showed such output :

>>> import podman
>>> client = podman.PodmanClient(base_url='unix:///run/podman/podman.sock')
>>> image = client.images.pull(repository='ubi8', tag='latest')
{'stream': 'Trying to pull ubi8:latest...\n'}
{'stream': 'Getting image source signatures\n'}
{'stream': 'Copying blob sha256:3de00bb8554b2c35c89412d5336f1fa469afc7b0160045dd08758d92c8a6b064\n'}
{'stream': 'Copying blob sha256:3de00bb8554b2c35c89412d5336f1fa469afc7b0160045dd08758d92c8a6b064\n'}
{'stream': 'Copying blob sha256:c530010fb61c513e7f06fa29484418fabf62924fc80cc8183ab671a3ce461a8e\n'}
{'stream': 'Copying blob sha256:c530010fb61c513e7f06fa29484418fabf62924fc80cc8183ab671a3ce461a8e\n'}
{'stream': 'Copying config sha256:552ac8ae4291e2a8d5622cff4a7f978d3032664b3946831a5606bde9bdedef2a\n'}
{'stream': 'Writing manifest to image destination\n'}
{'stream': 'Storing signatures\n'}
{'images': ['552ac8ae4291e2a8d5622cff4a7f978d3032664b3946831a5606bde9bdedef2a'], 'id': '552ac8ae4291e2a8d5622cff4a7f978d3032664b3946831a5606bde9bdedef2a'}

Unfortunately all of this prints are showed after image is pulled as the /images/pull is a blocking method.
I've tried similar method to logs with stream=True and api.stream_frames and even though it returned generator, the generator was filled after image was pulled.

My question is whether it is doable with current REST Api ?
Or are the changes on podman REST Api needed ?

Issue with the stats container method

I try to grab stats from my podman containers.

>>> import podman
>>> client = podman.PodmanClient(base_url="unix:///run/user/1000/podman/podman.sock")

>>> client.version()
{'Platform': {'Name': 'linux/amd64/ubuntu-22.04'}, 'Components': [{'Name': 'Podman Engine', 'Version': '3.4.4', 'Details': {'APIVersion': '3.4.4', 'Arch': 'amd64', 'BuildTime': '1970-01-01T01:00:00+01:00', 'Experimental': 'false', 'GitCommit': '', 'GoVersion': 'go1.17.3', 'KernelVersion': '5.15.0-48-generic', 'MinAPIVersion': '3.1.0', 'Os': 'linux'}}, {'Name': 'Conmon', 'Version': 'conmon version 2.0.25, commit: unknown', 'Details': {'Package': 'conmon: /usr/bin/conmon'}}, {'Name': 'OCI Runtime (crun)', 'Version': 'crun version 0.17\ncommit: 0e9229ae34caaebcb86f1fde18de3acaf18c6d9a\nspec: 1.0.0\n+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +YAJL', 'Details': {'Package': 'crun: /usr/bin/crun'}}], 'Version': '3.4.4', 'ApiVersion': '1.40', 'MinAPIVersion': '1.24', 'GitCommit': '', 'GoVersion': 'go1.17.3', 'Os': 'linux', 'Arch': 'amd64', 'KernelVersion': '5.15.0-48-generic', 'BuildTime': '1970-01-01T01:00:00+01:00'}

>>> containers = client.containers.list()
>>> containers
[<Container: 9491515251>, <Container: 1da5bc154a>]

First issue with stream=False:

>>> print(containers[1].stats(stream=False, decode=True))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/nicolargo/dev/glances/venv/lib/python3.10/site-packages/podman/domain/containers.py", line 393, in stats
    buffer.writer(json.dumps(entry) + "\n")

Second issue with stream=True (nothing is displayed...):

>>> for s in containers[1].stats(stream=True, decode=False):
...     print(s)

Information regarding my system:

  • OS: Ubuntu 22.04
  • Python: 3.10.6
  • Podman-py (installed with Pypi): 4.0.0

Question - How much refactoring per contribution would be allowed right now?

Hello! Let's get to the point. I just found out that this is the new official repo for the Python's podman lib and it targets the podman v2 which implements a ReST API interface for communications. Assuming that's all correct got a couple of question about contributing on the project:

1 - Is this project aiming to provide compatibility with the other library?

2 - If the answer for [1] is No then: How much code change would you allow at this current time? I notice that we are at the very beginning of the development and notice that we use a lot of functions around one big object (for connection). I would love to rework this using objects to make change on each of those layer easier that will definitively introduce a sort of full refactoring.

upstream management of gating tests for distro consumption

Fedora/RHEL etc. will need gating tests to be run along with the rpm updates. Something along the lines of podman-tests and buildah-tests subpackages that we already have.

podman and buildah tests are in bats, while podman-py tests are in python.

We need to decide on how to manage/maintain tests upstream so distros can easily consume them.

How to start containers with this module?

Hi I have this python module installed and a running socket, I am looking for a way to start a container with this module, similar to the docker.Client(version="1.22").start(some_container). I could find not find the relevant command with this podman module. Any help would be really great :)

Wrapper for podman pull?

I'm interested in a python client for podman that is more of a wrapper, e.g., allows me to pull a container from Python. Is this something that this library could support? From what I can see, it looks like the client here is intended to interact with the local socket (e.g., I can get containers / manifests that I've already pulled). It's fairly simple to use subprocess to interact with podman directly, but it would be great if the support was provided here! And if it's not and is not planned to, is there a reason why?

example in the README cannot run

README.md shows an example that is broken

symbols like system and images must be either imported individually, or qualified as podman.system
plus, ApiConnection is mispelled as APIConnection

podman.from_env() not working

Everytime I try podman.from_env() I get this error:

>>> import podman
>>> podman.from_env()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/podman/client.py", line 131, in from_env
    max_pool_size=max_pool_size,
  File "/usr/local/lib/python3.6/site-packages/podman/client.py", line 76, in __init__
    self.api = APIClient(**api_kwargs)
  File "/usr/local/lib/python3.6/site-packages/podman/api/client.py", line 116, in __init__
    self.base_url = self._normalize_url(base_url)
  File "/usr/local/lib/python3.6/site-packages/podman/api/client.py", line 159, in _normalize_url
    f"The scheme '{uri.scheme}' must be one of {APIClient.supported_schemes}"
ValueError: The scheme 'b''' must be one of ('unix', 'http+unix', 'ssh', 'http+ssh', 'tcp', 'http')

Have tried CentOS 8 stream with a native podman setup and MacOS with podman machine.

Are they any pre-reqs to be able to use podman.from_env() ?

Thanks

CentOS Stream release 8:

$ podman version
Client:       Podman Engine
Version:      4.2.0
API Version:  4.2.0
Go Version:   go1.18.4
Built:        Wed Sep 21 13:15:04 2022
OS/Arch:      linux/amd64

MacOS:

% podman version
Client:       Podman Engine
Version:      4.3.0
API Version:  4.3.0
Go Version:   go1.19
Git Commit:   ad42af94903ce4f3c3cd0693e4e17e4286bf094b
Built:        Wed Oct 19 15:33:33 2022
OS/Arch:      darwin/amd64

Server:       Podman Engine
Version:      4.3.1
API Version:  4.3.1
Go Version:   go1.19.2
Built:        Fri Nov 11 16:01:27 2022
OS/Arch:      linux/amd64

Offer to help

Hi 👋 ,

I just read the announcement that podman is getting a new API that also offers compatibility with Docker. Even though it might seem creepy since this repository is only three days old, I would like to offer my help on this. Currently, I am employed as a python developer, have some spare time soon and would like to use podman from now on. Also, since I have implemented a tool that currently uses the python library for docker quite heavily, I am willing to put some time in the podman API.

However, I have a question about this repository. As I understood it, the podman API will have a docker compatible API. Why not start by forking the official docker libraries and modifying them? There was a lot of work invested in building them, they work quite well and have no real shortcoming as far as I can tell. Especially docker-compose is a lot more advanced currently than podman-compose.

2 flavours of info()

Before yesterday's PR was merged, I had written on my side the following function in system/

def info(api):
    """Returns information on the system and libpod configuration"""
    path = api.join("/info")
    response = api.request("GET", path)
    return json.loads(response.read())

upon seeing the PR coming in I first thought we had come up with the exact same thing independently, since master now has this

def get_info(api):
    """Returns information on the system and libpod configuration"""
    try:
        response = api.request("GET", "/info")
        return json.loads(str(response.read(), 'utf-8'))
    except errors.NotFoundError as e:
        _report_not_found(e, e.response)

but there is a difference indeed with the call to api.join() that inserts the base in the target url
the fact is that both these work fine, but return completely different information

this is probably obvious to people familiar with the libpod API and REST in general but that came as a bit of a surprise to me; I'd appreciate any reference that would shed light on that

I guess this issue resonates with #22 a little, in the sense that the naming of these functions should probably outline their respective scope somehow

How do I set the ipc_mode to another container ?

I can't figure out the correct way to set the ipc_mode to another container in my run options.

options["ipc_mode"] = "container:my_container"

APIError: 500 Server Error: Internal Server Error (invalid config provided: invalid namespace type container:my_container specified)

podman exec available?

can we use this python client to execute commands on a container?

I see this method but don't know how to invoke it.

Getting logs from exec_run in a stream fashion

What I want to do is to get stdout/stderr of the command in exec_run line after line. I tried settung stream=True and also detach=True and then after retrieving logs, but no luck. I was only abailable to retrieve logs, once command in exec_run is executed.

Below example, where logs just hang and nothing happens.

from podman import PodmanClient

with PodmanClient() as client:
    client.containers.run(
        image="ubuntu",
        name="test",
        detach=True,
    )
    cmd = "apt-get update"

    print(cmd)
    res = client.containers.list()[-1].exec_run(
        cmd,
        detach=True,
    )
    print("before")
    print(res)
    logs = client.containers.list()[-1].logs(stream=True)

    for r in logs:
        print(r.decode("UTF-8"))

If I set stream=True, then bug in #201 will happen.

Is there a way to get these logs in a streamed way until fix for #201 is ready?

Question/Information required on some aspects of podman-py module

Hello,

I'm using podman-py for some container action, and I have a couple of questions;

  1. Is it possible to get real-time logging of what is happening during image build(from PodmanClient().images.build) in podman-py. I noticed that the option is available for pull(from PodmanClient().images.pull) with stream=True

  2. Does the PodmanClient support some kind of event loop that could be subscribed to, and receive the “stdout/stderr” as events regardless of podman command/method (build/pull) used?

  3. There is an issue (I think) with this line. The API doesn’t respect the REST endpoint, the REST returns a simple integer instead of JSON/dict.
    This prompts a TypeError, int object is not subscriptable

libpod

Empty environment variable is not supported

I guess this is supposed to happen to remove other empty parameters but it causes problem with empty environment variables. They get removed during data preparation in api/http_utils.py function _filter_values. So there is no way to use empty variable.

podman client hangs when starting container

Is this a BUG REPORT or FEATURE REQUEST? (leave only one on its own line)

/kind bug

Description

When trying to run a container (with possibly invalid configuration) via podman-py, causes the system service to hang. Killing the client call will still leave the service spinning.

❯ python -c 'import podman;podman.PodmanClient().containers.run(detach=True, image="docker.io/library/nginx", mounts=[{"target": "tests123", "source": "tests/", "mode": "bind"}], tty=True)'
^CTraceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/tmp/xyz/venv/lib/python3.9/site-packages/podman/domain/containers_run.py", line 66, in run
    container.start()
  File "/tmp/xyz/venv/lib/python3.9/site-packages/podman/domain/containers.py", line 350, in start
    response = self.client.post(
  File "/tmp/xyz/venv/lib/python3.9/site-packages/podman/api/client.py", line 304, in post
    return self._request(
  File "/tmp/xyz/venv/lib/python3.9/site-packages/podman/api/client.py", line 402, in _request
    self.request(
  File "/tmp/xyz/venv/lib/python3.9/site-packages/requests/sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "/tmp/xyz/venv/lib/python3.9/site-packages/requests/sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "/tmp/xyz/venv/lib/python3.9/site-packages/requests/adapters.py", line 439, in send
    resp = conn.urlopen(
  File "/tmp/xyz/venv/lib/python3.9/site-packages/urllib3/connectionpool.py", line 699, in urlopen
    httplib_response = self._make_request(
  File "/tmp/xyz/venv/lib/python3.9/site-packages/urllib3/connectionpool.py", line 445, in _make_request
    six.raise_from(e, None)
  File "<string>", line 3, in raise_from
  File "/tmp/xyz/venv/lib/python3.9/site-packages/urllib3/connectionpool.py", line 440, in _make_request
    httplib_response = conn.getresponse()
  File "/usr/lib/python3.9/http/client.py", line 1345, in getresponse
    response.begin()
  File "/usr/lib/python3.9/http/client.py", line 307, in begin
    version, status, reason = self._read_status()
  File "/usr/lib/python3.9/http/client.py", line 268, in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
  File "/usr/lib/python3.9/socket.py", line 704, in readinto
    return self._sock.recv_into(b)
KeyboardInterrupt
❯ podman run --mount=type=bind,source=tests/,destination=tests123 -d registry.fedoraproject.org/fedora
Error: invalid container path "tests123", must be an absolute path
❯ podman run --mount=type=bind,source=tests/,destination=/tests123 -t -d registry.fedoraproject.org/fedora
4b2829c8e699643859b55369d2d558198dc17f04d5d7c1597a4ac791258d62c6
❯ python -c 'import podman;podman.PodmanClient().containers.run(detach=True, image="docker.io/library/nginx", mounts=[{"target": "/tests123", "source": "tests/", "mode": "bind"}], tty=True)'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/tmp/xyz/venv/lib/python3.9/site-packages/podman/domain/containers_run.py", line 66, in run
    container.start()
  File "/tmp/xyz/venv/lib/python3.9/site-packages/podman/domain/containers.py", line 353, in start
    response.raise_for_status()
  File "/tmp/xyz/venv/lib/python3.9/site-packages/podman/api/client.py", line 65, in raise_for_status
    raise APIError(cause, response=self._response, explanation=message)
podman.errors.exceptions.APIError: 500 Server Error: Internal Server Error (invalid mount type for `/tests123`: OCI runtime error)

Steps to reproduce the issue:

mkdir xyz && cd xyz/
python -m venv venv; source venv/bin/activate
podman system service -t 0 &
pip install podman
podman pull registry.fedoraproject.org/fedora
python -c 'import podman;podman.PodmanClient().containers.run(detach=True, image="registry.fedoraproject.org/fedora", mounts=[{"target": "tests123", "source": "tests/", "mode": "bind"}], tty=True)'

Describe the results you received:
the podman client will hang while the podman service spins and stresses out the system.

Describe the results you expected:
Either incorrect configuration or a successful start + detach

Additional information you deem important (e.g. issue happens only occasionally):

Output of podman version:

Version:      3.1.2
API Version:  3.1.2
Go Version:   go1.16.4
Git Commit:   51b8ddbc22cf5b10dd76dd9243924aa66ad7db39
Built:        Sat May 22 16:22:34 2021
OS/Arch:      linux/amd64

Output of podman info --debug:

host:
  arch: amd64
  buildahVersion: 1.20.1
  cgroupManager: systemd
  cgroupVersion: v2
  conmon:
    package: /usr/bin/conmon is owned by conmon 1:2.0.28-1
    path: /usr/bin/conmon
    version: 'conmon version 2.0.28, commit: 6b18f7e0f2e4cd7f7b016b88141e82210d370008'
  cpus: 24
  distribution:
    distribution: arch
    version: unknown
  eventLogger: journald
  hostname: autumn
  idMappings:
    gidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 100000
      size: 65536
    uidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 100000
      size: 65536
  kernel: 5.12.7-arch1-1
  linkmode: dynamic
  memFree: 57026449408
  memTotal: 67362938880
  ociRuntime:
    name: crun
    package: /usr/bin/crun is owned by crun 0.19.1-1
    path: /usr/bin/crun
    version: |-
      crun version 0.19.1
      commit: 1535fedf0b83fb898d449f9680000f729ba719f5
      spec: 1.0.0
      +SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +YAJL
  os: linux
  remoteSocket:
    exists: true
    path: /run/user/1000/podman/podman.sock
  security:
    apparmorEnabled: false
    capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT
    rootless: true
    seccompEnabled: true
    selinuxEnabled: false
  slirp4netns:
    executable: /usr/bin/slirp4netns
    package: /usr/bin/slirp4netns is owned by slirp4netns 1.1.10-1
    version: |-
      slirp4netns version 1.1.10
      commit: baa2bc5ff12fe6db646c1f4f3f966526c0eba5a0
      libslirp: 4.5.0
      SLIRP_CONFIG_VERSION_MAX: 3
      libseccomp: 2.5.1
  swapFree: 1073737728
  swapTotal: 1073737728
  uptime: 10h 29m 51.81s (Approximately 0.42 days)
registries: {}
store:
  configFile: /home/jbpratt/.config/containers/storage.conf
  containerStore:
    number: 2
    paused: 0
    running: 0
    stopped: 2
  graphDriverName: overlay
  graphOptions: {}
  graphRoot: /home/jbpratt/.local/share/containers/storage
  graphStatus:
    Backing Filesystem: extfs
    Native Overlay Diff: "false"
    Supports d_type: "true"
    Using metacopy: "false"
  imageStore:
    number: 5
  runRoot: /run/user/1000/containers
  volumePath: /home/jbpratt/.local/share/containers/storage/volumes
version:
  APIVersion: 3.1.2
  Built: 1621718554
  BuiltTime: Sat May 22 16:22:34 2021
  GitCommit: 51b8ddbc22cf5b10dd76dd9243924aa66ad7db39
  GoVersion: go1.16.4
  OsArch: linux/amd64
  Version: 3.1.2

Have you tested with the latest version of Podman and have you checked the Podman Troubleshooting Guide? (https://github.com/containers/podman/blob/master/troubleshooting.md)

Yes

Additional environment details (AWS, VirtualBox, physical, etc.):
physical

unable to authenticate with PodmanClient

Hi,

is the implementation of either PodmanClient.login() or the handling of auth_config in images.push() on the roadmap? Is there any information available about the future of this project that we can access?

Podman events

Hi,

I'd like to make some kind of podman container service discovery.

Is it possible to watch for container create/delete events ?

Thank you in advance for your feedback

Keep up the great work 🎩

podman run not working

Hello,

I use the lib version 4.2.0, Python 3.10.4, podman 3.4.4.

If I try to use client.containers.run I get the following error:

>>> import podman
>>> 
>>> client = podman.PodmanClient()
>>> 
>>> client.images.pull("docker.io/library/ubuntu:20.04")
<Image: 'docker.io/library/ubuntu:20.04'>
>>> 
>>> image = client.images.pull("docker.io/library/ubuntu:20.04")
>>> 
>>> client.containers.run(image, ["ls", "/"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/kai/.local/lib/python3.10/site-packages/podman/domain/containers_run.py", line 80, in run
    exit_status = container.wait()["StatusCode"]
TypeError: 'int' object is not subscriptable
>>> 

Are I'm doing something wrong or is there a bug?

Thanks for the help
Kai

Error if URI exceeds 64 characters

I have a uri like this

uri = "unix:///Users/muzammil.shahbaz/.local/share/containers/podman/machine/podman-machine-default/podman.sock"
This exceeds the standard 64 characters.

On execution, I get the following error:

Exception has occurred: UnicodeError
encoding with 'idna' codec failed (UnicodeError: label empty or too long)

The above exception was the direct cause of the following exception:

  File "../podmanclient.py", line 12, in <module>
    version = client.version()

A potential fix would be to encode the URL to base64 and handle decoding in the code.

I am using podman version 4.1.1 on OSX using qemu virtual machine.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.