Skip to content

Commit

Permalink
Merge pull request #22319 from Luap99/exposed-ports-ps
Browse files Browse the repository at this point in the history
podman ps: show exposed ports under PORTS as well
  • Loading branch information
openshift-merge-bot[bot] authored Apr 12, 2024
2 parents 7b95a8a + 8de92ec commit 4b2c7f2
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 34 deletions.
24 changes: 18 additions & 6 deletions cmd/podman/containers/ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/docker/go-units"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/exp/slices"
)

var (
Expand Down Expand Up @@ -434,10 +435,7 @@ func (l psReporter) Networks() string {
// Ports converts from Portmappings to the string form
// required by ps
func (l psReporter) Ports() string {
if len(l.ListContainer.Ports) < 1 {
return ""
}
return portsToString(l.ListContainer.Ports)
return portsToString(l.ListContainer.Ports, l.ListContainer.ExposedPorts)
}

// CreatedAt returns the container creation time in string format. podman
Expand Down Expand Up @@ -489,8 +487,8 @@ func (l psReporter) UTS() string {
// portsToString converts the ports used to a string of the from "port1, port2"
// and also groups a continuous list of ports into a readable format.
// The format is IP:HostPort(-Range)->ContainerPort(-Range)/Proto
func portsToString(ports []types.PortMapping) string {
if len(ports) == 0 {
func portsToString(ports []types.PortMapping, exposedPorts map[uint16][]string) string {
if len(ports) == 0 && len(exposedPorts) == 0 {
return ""
}
sb := &strings.Builder{}
Expand All @@ -512,6 +510,20 @@ func portsToString(ports []types.PortMapping) string {
}
}
}

// iterating a map is not deterministic so let's convert slice first and sort by port to make it deterministic
sortedPorts := make([]uint16, 0, len(exposedPorts))
for port := range exposedPorts {
sortedPorts = append(sortedPorts, port)
}
slices.Sort(sortedPorts)
for _, port := range sortedPorts {
for _, protocol := range exposedPorts[port] {
// exposed ports do not have a host part and are just written as "NUM/PROTO"
fmt.Fprintf(sb, "%d/%s, ", port, protocol)
}
}

display := sb.String()
// make sure to trim the last ", " of the string
return display[:len(display)-2]
Expand Down
10 changes: 7 additions & 3 deletions docs/source/markdown/options/expose.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
####> podman create, run
####> If file is edited, make sure the changes
####> are applicable to all of those.
#### **--expose**=*port*
#### **--expose**=*port[/protocol]*

Expose a port, or a range of ports (e.g. **--expose=3300-3310**) to set up port redirection
on the host system.
Expose a port or a range of ports (e.g. **--expose=3300-3310**).
The protocol can be `tcp`, `udp` or `sctp` and if not given `tcp` is assumed.
This option matches the EXPOSE instruction for image builds and has no effect on
the actual networking rules unless **-P/--publish-all** is used to forward to all
exposed ports from random host ports. To forward specific ports from the host
into the container use the **-p/--publish** option instead.
3 changes: 2 additions & 1 deletion docs/source/markdown/podman-ps.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Valid placeholders for the Go template are listed below:
| .ExitCode | Container exit code |
| .Exited | "true" if container has exited |
| .ExitedAt | Time (epoch seconds) that container exited |
| .ExposedPorts ... | Map of exposed ports on this container |
| .ID | Container ID |
| .Image | Image Name/ID |
| .ImageID | Image ID |
Expand All @@ -92,7 +93,7 @@ Valid placeholders for the Go template are listed below:
| .Pid | Process ID on host system |
| .Pod | Pod the container is associated with (SHA) |
| .PodName | PodName of the container |
| .Ports | Exposed ports |
| .Ports | Forwarded and exposed ports |
| .Restarts | Display the container restart count |
| .RunningFor | Time elapsed since container was started |
| .Size | Size of container |
Expand Down
5 changes: 5 additions & 0 deletions pkg/domain/entities/types/container_ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ type ListContainer struct {
ExitedAt int64
// If container has exited, the return code from the command
ExitCode int32
// ExposedPorts contains the ports that are exposed but not forwarded,
// see Ports for forwarded ports.
// The key is the port number and the string slice contains the protocols,
// i.e. "tcp", "udp" and "sctp".
ExposedPorts map[uint16][]string
// The unique identifier for the container
ID string `json:"Id"`
// Container image
Expand Down
47 changes: 24 additions & 23 deletions pkg/ps/ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,29 +238,30 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
}

ps := entities.ListContainer{
AutoRemove: ctr.AutoRemove(),
CIDFile: conConfig.Spec.Annotations[define.InspectAnnotationCIDFile],
Command: conConfig.Command,
Created: conConfig.CreatedTime,
ExitCode: exitCode,
Exited: exited,
ExitedAt: exitedTime.Unix(),
ID: conConfig.ID,
Image: conConfig.RootfsImageName,
ImageID: conConfig.RootfsImageID,
IsInfra: conConfig.IsInfra,
Labels: conConfig.Labels,
Mounts: ctr.UserVolumes(),
Names: []string{conConfig.Name},
Networks: networks,
Pid: pid,
Pod: conConfig.Pod,
Ports: portMappings,
Restarts: restartCount,
Size: size,
StartedAt: startedTime.Unix(),
State: conState.String(),
Status: healthStatus,
AutoRemove: ctr.AutoRemove(),
CIDFile: conConfig.Spec.Annotations[define.InspectAnnotationCIDFile],
Command: conConfig.Command,
Created: conConfig.CreatedTime,
ExitCode: exitCode,
Exited: exited,
ExitedAt: exitedTime.Unix(),
ExposedPorts: conConfig.ExposedPorts,
ID: conConfig.ID,
Image: conConfig.RootfsImageName,
ImageID: conConfig.RootfsImageID,
IsInfra: conConfig.IsInfra,
Labels: conConfig.Labels,
Mounts: ctr.UserVolumes(),
Names: []string{conConfig.Name},
Networks: networks,
Pid: pid,
Pod: conConfig.Pod,
Ports: portMappings,
Restarts: restartCount,
Size: size,
StartedAt: startedTime.Unix(),
State: conState.String(),
Status: healthStatus,
}
if opts.Pod && len(conConfig.Pod) > 0 {
podName, err := rt.GetPodName(conConfig.Pod)
Expand Down
12 changes: 11 additions & 1 deletion test/e2e/container_inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,19 @@ var _ = Describe("Podman container inspect", func() {

It("podman inspect shows exposed ports", func() {
name := "testcon"
session := podmanTest.Podman([]string{"run", "-d", "--stop-timeout", "0", "--expose", "8787/udp", "--name", name, ALPINE, "sleep", "inf"})
session := podmanTest.Podman([]string{"run", "-d", "--stop-timeout", "0", "--expose", "8787/udp", "--name", name, ALPINE, "sleep", "100"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
data := podmanTest.InspectContainer(name)

Expect(data).To(HaveLen(1))
Expect(data[0].NetworkSettings.Ports).
To(Equal(map[string][]define.InspectHostPort{"8787/udp": nil}))

session = podmanTest.Podman([]string{"ps", "--format", "{{.Ports}}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
Expect(session.OutputToString()).To(Equal("8787/udp"))
})

It("podman inspect shows exposed ports on image", func() {
Expand All @@ -46,6 +51,11 @@ var _ = Describe("Podman container inspect", func() {
Expect(data).To(HaveLen(1))
Expect(data[0].NetworkSettings.Ports).
To(Equal(map[string][]define.InspectHostPort{"80/tcp": nil, "8989/tcp": nil}))

session = podmanTest.Podman([]string{"ps", "--format", "{{.Ports}}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
Expect(session.OutputToString()).To(Equal("80/tcp, 8989/tcp"))
})

It("podman inspect shows volumes-from with mount options", func() {
Expand Down

1 comment on commit 4b2c7f2

@packit-as-a-service
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

podman-next COPR build failed. @containers/packit-build please check.

Please sign in to comment.