mirror of
https://github.com/containers/podman.git
synced 2025-05-17 23:26:08 +08:00
podman ps: show exposed ports under PORTS as well
Docker shows exposed ports as just PORT/PROTO so match that behavior. It is not clear to me why someone needs that information in ps as "expose" doesn't effect anything networking related. Fixes https://issues.redhat.com/browse/RHEL-32154 Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
@ -20,6 +20,7 @@ import (
|
||||
"github.com/docker/go-units"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -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
|
||||
@ -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{}
|
||||
@ -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]
|
||||
|
@ -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 |
|
||||
@ -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 |
|
||||
|
@ -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
|
||||
|
47
pkg/ps/ps.go
47
pkg/ps/ps.go
@ -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)
|
||||
|
@ -26,7 +26,7 @@ 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)
|
||||
@ -34,6 +34,11 @@ var _ = Describe("Podman container inspect", func() {
|
||||
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() {
|
||||
@ -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() {
|
||||
|
Reference in New Issue
Block a user