podman-compose port does not work with dynamic host port
If a container does not have a specific host port mapping for its internal port it will be given a dynamic port on the host when it is started (this is useful if you want to have more than one instance of the container on the same host without conflicts).
This is the primary use case for the podman port command—precisely to query podman to figure out what random port your service received. While podman-compose does offer a similar command podman-compose port for this situation, it seems to only work on port mappings with a specific host port.
Describe the bug
If podman-compose port is run to query a port for a container that does not have a specific host mapping, podman-compose crashes with a value error because it tries to unpack the result of splitting a string expecting to find at least two pieces.
To Reproduce Create a compose file with a service that has an internal port it listens on and add a port mapping that mentions the number of the internal port but does not specify a host port to map it to. Run podman-compose port with the name of the service and the number of the internal port.
Expected behavior The mapping that podman chose for the internal port on the host is printed
Actual behavior Python stack trace and crash output due to unhandled value error exception
Output
example compose file
services:
example:
image: busybox
command: httpd -f -p 80 -h /tmp
ports:
- "80"
commands that demonstrate the issue
$ podman-compose up -d
2522d6eeed43ad011db9300d901101f53fe6cf30c3b7c97073ce7b90f32974be
Resolved "busybox" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/busybox:latest...
Getting image source signatures
Copying blob 3d1a87f2317d done |
Copying config 87ff76f62d done |
Writing manifest to image destination
cd58e63445c33df91487869478f7d2b352603ff3e665873dcceb44489d1b982c
foo_example_1
$ podman-compose port example 80
Traceback (most recent call last):
File "podman_compose.py", line 3530, in <module>
main()
File "podman_compose.py", line 3526, in main
asyncio.run(async_main())
File "/usr/lib64/python3.12/asyncio/runners.py", line 194, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.12/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.12/asyncio/base_events.py", line 685, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "podman_compose.py", line 3522, in async_main
await podman_compose.run()
File "podman_compose.py", line 1755, in run
retcode = await cmd(self, args)
^^^^^^^^^^^^^^^^^^^^^
File "podman_compose.py", line 2921, in compose_port
published, target = _published_target(p)
^^^^^^^^^^^^^^^^^^^^
File "podman_compose.py", line 2910, in _published_target
published, target = port_string.split(":")[-2:]
^^^^^^^^^^^^^^^^^
ValueError: not enough values to unpack (expected 2, got 1)
$ podman port foo_example_1 80
0.0.0.0:33737
Environment:
- OS: Linux (Fedora 39)
- podman version: 4.9.3
- podman compose version:
$ git describe HEAD
v1.2.0-72-g229650c
$ git show --oneline
229650c (HEAD -> main, upstream/main) Merge pull request #1032 from shuckc/main