github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/cmd/podman/port.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/containers/libpod/cmd/podman/cliconfig"
     9  	"github.com/containers/libpod/pkg/adapter"
    10  	"github.com/docker/go-connections/nat"
    11  	"github.com/pkg/errors"
    12  	"github.com/spf13/cobra"
    13  )
    14  
    15  var (
    16  	portCommand     cliconfig.PortValues
    17  	portDescription = `List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT
    18  `
    19  	_portCommand = &cobra.Command{
    20  		Use:   "port [flags] CONTAINER [PORT]",
    21  		Short: "List port mappings or a specific mapping for the container",
    22  		Long:  portDescription,
    23  		RunE: func(cmd *cobra.Command, args []string) error {
    24  			portCommand.InputArgs = args
    25  			portCommand.GlobalFlags = MainGlobalOpts
    26  			portCommand.Remote = remoteclient
    27  			return portCmd(&portCommand)
    28  		},
    29  		Args: func(cmd *cobra.Command, args []string) error {
    30  			return checkAllLatestAndCIDFile(cmd, args, true, false)
    31  		},
    32  		Example: `podman port --all
    33    podman port ctrID 80/tcp
    34    podman port --latest 80`,
    35  	}
    36  )
    37  
    38  func init() {
    39  	portCommand.Command = _portCommand
    40  	portCommand.SetHelpTemplate(HelpTemplate())
    41  	portCommand.SetUsageTemplate(UsageTemplate())
    42  	flags := portCommand.Flags()
    43  
    44  	flags.BoolVarP(&portCommand.All, "all", "a", false, "Display port information for all containers")
    45  	flags.BoolVarP(&portCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
    46  
    47  	markFlagHiddenForRemoteClient("latest", flags)
    48  }
    49  
    50  func portCmd(c *cliconfig.PortValues) error {
    51  	var (
    52  		userPort nat.Port
    53  		err      error
    54  	)
    55  	args := c.InputArgs
    56  
    57  	if c.Latest && c.All {
    58  		return errors.Errorf("the 'all' and 'latest' options cannot be used together")
    59  	}
    60  	if c.All && len(args) > 0 {
    61  		return errors.Errorf("no additional arguments can be used with 'all'")
    62  	}
    63  	if len(args) == 0 && !c.Latest && !c.All {
    64  		return errors.Errorf("you must supply a running container name or id")
    65  	}
    66  
    67  	port := ""
    68  	if len(args) > 1 && !c.Latest {
    69  		port = args[1]
    70  	}
    71  	if len(args) == 1 && c.Latest {
    72  		port = args[0]
    73  	}
    74  	if len(port) > 0 {
    75  		fields := strings.Split(port, "/")
    76  		if len(fields) > 2 || len(fields) < 1 {
    77  			return errors.Errorf("port formats are port/protocol. '%s' is invalid", port)
    78  		}
    79  		if len(fields) == 1 {
    80  			fields = append(fields, "tcp")
    81  		}
    82  
    83  		userPort, err = nat.NewPort(fields[1], fields[0])
    84  		if err != nil {
    85  			return err
    86  		}
    87  	}
    88  
    89  	runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
    90  	if err != nil {
    91  		return errors.Wrapf(err, "could not get runtime")
    92  	}
    93  	defer runtime.DeferredShutdown(false)
    94  	containers, err := runtime.Port(c)
    95  	if err != nil {
    96  		return err
    97  	}
    98  	for _, con := range containers {
    99  		portmappings, err := con.PortMappings()
   100  		if err != nil {
   101  			return err
   102  		}
   103  		var found bool
   104  		// Iterate mappings
   105  		for _, v := range portmappings {
   106  			hostIP := v.HostIP
   107  			// Set host IP to 0.0.0.0 if blank
   108  			if hostIP == "" {
   109  				hostIP = "0.0.0.0"
   110  			}
   111  			if c.All {
   112  				fmt.Printf("%s\t", con.ID()[:12])
   113  			}
   114  			// If not searching by port or port/proto, then dump what we see
   115  			if port == "" {
   116  				fmt.Printf("%d/%s -> %s:%d\n", v.ContainerPort, v.Protocol, hostIP, v.HostPort)
   117  				continue
   118  			}
   119  			containerPort, err := nat.NewPort(v.Protocol, strconv.Itoa(int(v.ContainerPort)))
   120  			if err != nil {
   121  				return err
   122  			}
   123  			if containerPort == userPort {
   124  				fmt.Printf("%s:%d\n", hostIP, v.HostPort)
   125  				found = true
   126  				break
   127  			}
   128  		}
   129  		if !found && port != "" {
   130  			return errors.Errorf("failed to find published port %q", port)
   131  		}
   132  	}
   133  
   134  	return nil
   135  }