Merge pull request #252 from baude/port

podman port
This commit is contained in:
Daniel J Walsh
2018-01-24 21:24:54 +01:00
committed by GitHub
6 changed files with 263 additions and 0 deletions

View File

@ -57,6 +57,7 @@ func main() {
mountCommand,
pauseCommand,
psCommand,
portCommand,
pullCommand,
pushCommand,
rmCommand,

145
cmd/podman/port.go Normal file
View 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
}

View File

@ -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)|

View File

@ -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
View 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
View 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 ]
}