mirror of
https://github.com/containers/podman
synced 2024-10-20 09:13:46 +00:00
podman port
podman port reports the port mappings per container. it can be used to report the ports ofa single container or latest container or all containers. in the case of a single container, the user can add an option filter for port and protocol. Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
parent
a03e040f0b
commit
b74e38b042
|
@ -57,6 +57,7 @@ func main() {
|
|||
mountCommand,
|
||||
pauseCommand,
|
||||
psCommand,
|
||||
portCommand,
|
||||
pullCommand,
|
||||
pushCommand,
|
||||
rmCommand,
|
||||
|
|
145
cmd/podman/port.go
Normal file
145
cmd/podman/port.go
Normal file
|
@ -0,0 +1,145 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectatomic/libpod/libpod"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
portFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "display port information for all containers",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
portDescription = `
|
||||
podman port
|
||||
|
||||
List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT
|
||||
`
|
||||
|
||||
portCommand = cli.Command{
|
||||
Name: "port",
|
||||
Usage: "List port mappings or a specific mapping for the container",
|
||||
Description: portDescription,
|
||||
Flags: portFlags,
|
||||
Action: portCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [mapping]",
|
||||
}
|
||||
)
|
||||
|
||||
func portCmd(c *cli.Context) error {
|
||||
var (
|
||||
userProto, containerName string
|
||||
userPort int
|
||||
container *libpod.Container
|
||||
containers []*libpod.Container
|
||||
)
|
||||
|
||||
args := c.Args()
|
||||
if err := validateFlags(c, portFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Bool("latest") && c.Bool("all") {
|
||||
return errors.Errorf("the 'all' and 'latest' options cannot be used together")
|
||||
}
|
||||
if c.Bool("all") && len(args) > 0 {
|
||||
return errors.Errorf("no additional arguments can be used with 'all'")
|
||||
}
|
||||
if len(args) == 0 && !c.Bool("latest") && !c.Bool("all") {
|
||||
return errors.Errorf("you must supply a running container name or id")
|
||||
}
|
||||
if !c.Bool("latest") && !c.Bool("all") {
|
||||
containerName = args[0]
|
||||
}
|
||||
|
||||
port := ""
|
||||
if len(args) > 1 && !c.Bool("latest") {
|
||||
port = args[1]
|
||||
}
|
||||
if len(args) == 1 && c.Bool("latest") {
|
||||
port = args[0]
|
||||
}
|
||||
if port != "" {
|
||||
fields := strings.Split(port, "/")
|
||||
// User supplied at least port
|
||||
var err error
|
||||
// User supplied port and protocol
|
||||
if len(fields) == 2 {
|
||||
userProto = fields[1]
|
||||
}
|
||||
if len(fields) >= 1 {
|
||||
p := fields[0]
|
||||
userPort, err = strconv.Atoi(p)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to format port")
|
||||
}
|
||||
}
|
||||
// Format is incorrect
|
||||
if len(fields) > 2 || len(fields) < 1 {
|
||||
return errors.Errorf("port formats are port/protocol. '%s' is invalid", port)
|
||||
}
|
||||
}
|
||||
|
||||
runtime, err := getRuntime(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if !c.Bool("latest") && !c.Bool("all") {
|
||||
container, err = runtime.LookupContainer(containerName)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to find container %s", containerName)
|
||||
}
|
||||
containers = append(containers, container)
|
||||
} else if c.Bool("latest") {
|
||||
container, err = runtime.GetLatestContainer()
|
||||
containers = append(containers, container)
|
||||
} else {
|
||||
containers, err = runtime.GetRunningContainers()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to get all containers")
|
||||
}
|
||||
}
|
||||
|
||||
for _, con := range containers {
|
||||
if state, _ := con.State(); state != libpod.ContainerStateRunning {
|
||||
continue
|
||||
}
|
||||
if c.Bool("all") {
|
||||
fmt.Println(con.ID())
|
||||
}
|
||||
// Iterate mappings
|
||||
for _, v := range con.Config().PortMappings {
|
||||
hostIP := v.HostIP
|
||||
// Set host IP to 0.0.0.0 if blank
|
||||
if hostIP == "" {
|
||||
hostIP = "0.0.0.0"
|
||||
}
|
||||
// If not searching by port or port/proto, then dump what we see
|
||||
if port == "" {
|
||||
fmt.Printf("%d/%s -> %s:%d\n", v.ContainerPort, v.Protocol, hostIP, v.HostPort)
|
||||
continue
|
||||
}
|
||||
// We have a match on ports
|
||||
if v.ContainerPort == int32(userPort) {
|
||||
if userProto == "" || userProto == v.Protocol {
|
||||
fmt.Printf("%s:%d", hostIP, v.HostPort)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
return errors.Errorf("No public port '%d' published for %s", userPort, containerName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
| [podman-logs(1)](/docs/podman-logs.1.md) | Display the logs of a container |[![...](/docs/play.png)](https://asciinema.org/a/MZPTWD5CVs3dMREkBxQBY9C5z)|
|
||||
| [podman-mount(1)](/docs/podman-mount.1.md) | Mount a working container's root filesystem |[![...](/docs/play.png)](https://asciinema.org/a/YSP6hNvZo0RGeMHDA97PhPAf3)|
|
||||
| [podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers |[![...](/docs/play.png)](https://asciinema.org/a/141292)|
|
||||
| [podman-port(1)](/docs/podman-port.1.md) | List port mappings for running containers |[![...](/docs/play.png)]()|
|
||||
| [podman-ps(1)](/docs/podman-ps.1.md) | Prints out information about containers |[![...](/docs/play.png)](https://asciinema.org/a/bbT41kac6CwZ5giESmZLIaTLR)|
|
||||
| [podman-pull(1)](/docs/podman-pull.1.md) | Pull an image from a registry |[![...](/docs/play.png)](https://asciinema.org/a/lr4zfoynHJOUNu1KaXa1dwG2X)|
|
||||
| [podman-push(1)](/docs/podman-push.1.md) | Push an image to a specified destination |[![...](/docs/play.png)](https://asciinema.org/a/133276)|
|
||||
|
|
|
@ -1413,6 +1413,18 @@ _podman_pause() {
|
|||
_complete_ "$options_with_args" "$boolean_options"
|
||||
}
|
||||
|
||||
_podman_port() {
|
||||
local options_with_args="
|
||||
--help -h
|
||||
"
|
||||
local boolean_options="
|
||||
--all
|
||||
-a
|
||||
-l
|
||||
--latest"
|
||||
_complete_ "$options_with_args" "$boolean_options"
|
||||
}
|
||||
|
||||
_podman_ps() {
|
||||
local options_with_args="
|
||||
--filter -f
|
||||
|
@ -1566,6 +1578,7 @@ _podman_podman() {
|
|||
logs
|
||||
mount
|
||||
pause
|
||||
port
|
||||
ps
|
||||
pull
|
||||
push
|
||||
|
|
60
docs/podman-port.1.md
Normal file
60
docs/podman-port.1.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
% podman(1) podman-port - List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT
|
||||
% Brent Baude
|
||||
# podman-port "1" "January 2018" "podman"
|
||||
|
||||
## NAME
|
||||
podman port - List port mappings for a container
|
||||
|
||||
## SYNOPSIS
|
||||
**podman port [OPTIONS] CONTAINER [PRIVATE_PORT[/PROTO]]**
|
||||
|
||||
## DESCRIPTION
|
||||
List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT
|
||||
|
||||
## OPTIONS
|
||||
|
||||
**--all, a**
|
||||
|
||||
List all known port mappings for running containers. When using this option, you cannot pass any container names
|
||||
or private ports/protocols as filters.
|
||||
|
||||
**--latest, -l**
|
||||
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
|
||||
to run containers such as CRI-O, the last started container could be from either of those methods.
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
List all port mappings
|
||||
```
|
||||
#podman port -a
|
||||
b4d2f05432e482e017b1a4b2eae15fa7b4f6fb7e9f65c1bde46294fdef285906
|
||||
80/udp -> 0.0.0.0:44327
|
||||
80/tcp -> 0.0.0.0:44327
|
||||
#
|
||||
```
|
||||
|
||||
List port mappings for a specific container
|
||||
```
|
||||
#podman port b4d2f054
|
||||
80/udp -> 0.0.0.0:44327
|
||||
80/tcp -> 0.0.0.0:44327
|
||||
#
|
||||
```
|
||||
List the port mappings for the latest container and port 80
|
||||
```
|
||||
#podman port b4d2f054 80
|
||||
0.0.0.0:44327
|
||||
#
|
||||
```
|
||||
|
||||
List the port mappings for a specific container for port 80 and the tcp protocol.
|
||||
```
|
||||
#podman port b4d2f054 80/tcp
|
||||
0.0.0.0:44327
|
||||
#
|
||||
```
|
||||
## SEE ALSO
|
||||
podman(1), podan-inspect(1)
|
||||
|
||||
## HISTORY
|
||||
January 2018, Originally compiled by Brent Baude <bbaude@redhat.com>
|
43
test/podman_port.bats
Normal file
43
test/podman_port.bats
Normal file
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
function teardown() {
|
||||
cleanup_test
|
||||
}
|
||||
|
||||
function setup() {
|
||||
copy_images
|
||||
}
|
||||
|
||||
@test "podman port all and latest" {
|
||||
run ${PODMAN_BINARY} ${PODMAN_OPTIONS} port -a -l
|
||||
echo "$output"
|
||||
echo "$status"
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "podman port all and extra" {
|
||||
run ${PODMAN_BINARY} ${PODMAN_OPTIONS} port -a foobar
|
||||
echo "$output"
|
||||
echo "$status"
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "podman port nginx" {
|
||||
run ${PODMAN_BINARY} ${PODMAN_OPTIONS} run -dt -P docker.io/library/nginx:latest
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
run ${PODMAN_BINARY} ${PODMAN_OPTIONS} port -l
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
run ${PODMAN_BINARY} ${PODMAN_OPTIONS} port -l 80
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
run ${PODMAN_BINARY} ${PODMAN_OPTIONS} port -l 80/tcp
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
run ${PODMAN_BINARY} ${PODMAN_OPTIONS} port -a
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
Loading…
Reference in a new issue