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

TypeError when trying to get container instance status #446

Open
JacobCallahan opened this issue Oct 14, 2024 · 9 comments
Open

TypeError when trying to get container instance status #446

JacobCallahan opened this issue Oct 14, 2024 · 9 comments

Comments

@JacobCallahan
Copy link
Contributor

When trying to get the status of a container instance running on a remote podman host, I get the following error.

Out[5]: <Container: 859c3172e0>

In [6]: container_inst.id
Out[6]: '859c3172e0de5e27934ba7bcbd190d0949227bfe973ded77658d25f30a1585c2'

In [7]: container_inst.status
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[7], line 1
----> 1 container_inst.status

File ~/Programming/broker/.venv/lib64/python3.12/site-packages/podman/domain/containers.py:54, in Container.status(self)
     52 """Literal["running", "stopped", "exited", "unknown"]: Returns status of container."""
     53 with suppress(KeyError):
---> 54     return self.attrs["State"]["Status"]
     55 return "unknown"

TypeError: string indices must be integers, not 'str'

When checking the value of attrs for the instance, I see that status isn't nested under state.

In [1]: self.attrs                                                                                                                                                                            
Out[1]:                                                                                                                                                                                       
{'AutoRemove': False,                                                                                                                                                                         
 'Command': ['/bin/sh', '-c', '/tmp/startup.sh'],
...
 'StartedAt': 1728929152,
 'State': 'running',
 'Status': ''}

There is also a possibility that this is due to a difference in major podman versions.

Local Podman: podman-5.2.3-1.fc40.x86_64
Local podman-py: 5.0.0
Remote Podman: podman-4.9.4-4

@inknos
Copy link
Contributor

inknos commented Oct 16, 2024

@JacobCallahan thanks for the report, I think it could be due to Podman 4 on the host and Podman 5 on the client. Do you have the chance to try with the same major versions?

@JacobCallahan
Copy link
Contributor Author

@inknos unfortunately, I don't have a remote podman host now, but could potentially set one up on Friday or next week.

@inknos
Copy link
Contributor

inknos commented Oct 17, 2024

@JacobCallahan , I tried to reproduce it and it works on my system with podman 5 in the host and podman 4 in the server. I think trying with podman 5 in both is not necessary.

>>> url = "ssh://[email protected]/run/user/1000/podman/podman.sock"
>>> from podman import PodmanClient
>>> client = PodmanClient(base_url=url, identity="/home/nsella/.ssh/id_rsa")
>>> client.containers.list()
[<Container: fd7dec82e8>, ... ]
>>> c = client.containers.get("fd7dec82e8")
>>> c.id
'fd7dec82e85daac28395403fc130411c6ee72e4b4d73e4a9ecf56dceeed42390'
>>> c.status
'running'

Host: podman version 5.3.0-dev-27d73b0cd
Server: podman version 4.9.4-rhel
PodmanPy: upstream and 5.0.0


Please provide more information on your issue. do my steps reproduce the issue for you? if not, could you provide reproducing steps?

@JacobCallahan
Copy link
Contributor Author

@inknos so i found something interesting while testing your steps. Your steps worked fine, when acting on a container object from get, but not on the container objects returned from list.

In [6]: url = "tcp://infra-podman-ipv4.our.lab.com:2375"

In [7]: client = PodmanClient(base_url=url)

In [8]: client.containers.list()
Out[8]: 
[<Container: abb2858b55>,
 <Container: f4539e8307>,
 <Container: 8c106a4a5a>,
 <Container: 6b9a4e97a2>,
 <Container: 43850b849c>,
 <Container: 7f5afe54bf>,
 <Container: e27ea6295c>,
 <Container: c13ed5f868>,
 <Container: 859c3172e0>,
 <Container: acefe65b89>]

In [9]: c = client.containers.get("abb2858b55")

In [10]: c.id
Out[10]: 'abb2858b558831055a74c9b79f4db1bf0e60b7c3f47a144ee05fe9c59edebeae'

In [11]: c.status
Out[11]: 'running'

In [12]: for c in client.containers.list():
    ...:     print(c.id)
    ...:     print(c.status)
    ...: 
abb2858b558831055a74c9b79f4db1bf0e60b7c3f47a144ee05fe9c59edebeae
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[12], line 3
      1 for c in client.containers.list():
      2     print(c.id)
----> 3     print(c.status)

File ~/Programming/broker/.venv/lib64/python3.12/site-packages/podman/domain/containers.py:54, in Container.status(self)
     52 """Literal["running", "stopped", "exited", "unknown"]: Returns status of container."""
     53 with suppress(KeyError):
---> 54     return self.attrs["State"]["Status"]
     55 return "unknown"

TypeError: string indices must be integers, not 'str'

In [13]: containers = client.containers.list()

In [14]: containers[0].id
Out[14]: 'abb2858b558831055a74c9b79f4db1bf0e60b7c3f47a144ee05fe9c59edebeae'

In [15]: containers[0].status
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[15], line 1
----> 1 containers[0].status

File ~/Programming/broker/.venv/lib64/python3.12/site-packages/podman/domain/containers.py:54, in Container.status(self)
     52 """Literal["running", "stopped", "exited", "unknown"]: Returns status of container."""
     53 with suppress(KeyError):
---> 54     return self.attrs["State"]["Status"]
     55 return "unknown"

TypeError: string indices must be integers, not 'str'

@inknos
Copy link
Contributor

inknos commented Oct 17, 2024

right, so the issue is that the container status need to be reloaded in order to access it from the list. note that the inspect call is expensive, that's why you need to run reload explicitly.

clist = client.containers.list()
for c in clist:
    c.reload()
print(clist[0].status)

with this you should get the status.

I would not touch too much the reload function but something I would consider is handling such exceptions with a try like

@property
def status(self):
    """Literal["running", "stopped", "exited", "unknown"]: Returns status of container."""
    with suppress(KeyError):
        try:
            return self.attrs["State"]["Status"]
        except TypeError as e:
            # stderr or log something useful here
            # probably even raise e again since I am not sure TypeError would isolate this issue
    return "unknown"

@inknos
Copy link
Contributor

inknos commented Oct 17, 2024

cc: @jwhonce TL;DR: we are once again discussing status property exceptions when it's invoked after a container.list call

inknos added a commit to inknos/podman-py that referenced this issue Oct 17, 2024
After calling containers.list each container does not have the status
correctly fetched. With reload it will return a list of reloaded
containers

Fixes: containers#446

Signed-off-by: Nicola Sella <[email protected]>
inknos added a commit to inknos/podman-py that referenced this issue Oct 17, 2024
After calling containers.list each container does not have the status
correctly fetched. It will now return a list of reloaded container

client = PodmanClient()
clist = client.containers.list() # reloads every container now
clist[0].status

Fixes: containers#446

Signed-off-by: Nicola Sella <[email protected]>
inknos added a commit to inknos/podman-py that referenced this issue Oct 17, 2024
Status should return unknown when TypeError occours. This exception can
be thrown after containers.list() is called and c.status is accessed
before c.reload()

client = PodmanClient()
clist = client.containers.list()
clist[0].status # TypeError without fix

Fixes: containers#446

Signed-off-by: Nicola Sella <[email protected]>
inknos added a commit to inknos/podman-py that referenced this issue Oct 17, 2024
After calling containers.list each container does not have the status
correctly fetched. It will now return a list of reloaded container

client = PodmanClient()
clist = client.containers.list() # reloads every container now
clist[0].status

Fixes: containers#446

Signed-off-by: Nicola Sella <[email protected]>
inknos added a commit to inknos/podman-py that referenced this issue Oct 17, 2024
After calling containers.list each container does not have the status
correctly fetched. It will now return a list of reloaded container

client = PodmanClient()
clist = client.containers.list() # reloads every container now
clist[0].status

Fixes: containers#446

Signed-off-by: Nicola Sella <[email protected]>
@inknos
Copy link
Contributor

inknos commented Oct 17, 2024

I would propose two approaches

  1. containers.list calls c.reload() before return - 2c6806b

  2. c.status return "unknown" if TypeError - fa92dd7

@JacobCallahan
Copy link
Contributor Author

JacobCallahan commented Oct 17, 2024

The expense has to be paid by someone, to be fair.

As a user, I would expect the Container objects from list to be the same as those from get. Having to get the initial list of container objects, then iterating over those objects just to pull the full information again doesn't seem ideal.

I've worked around this issue for my team's use with a try/except in the meantime.

    try:
        info["status"] = container_inst.status
    except TypeError:
        info["status"] = container_inst.attrs["State"]

edit:
If the intention isn't to have the container object be complete when returning from list, then you could just return a list of ids and make sure users call get manually. This would certainly speed things up from that perspective..

@jwhonce
Copy link
Member

jwhonce commented Oct 18, 2024

@inknos I would rather see us implement the sparse keyword for list(). It is currently ignored.

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

No branches or pull requests

3 participants