瀏覽代碼

port: improve error-handling if port not found (#10039)

This method looked slightly incomplete. If the port wasn't found,
it'd return `err`, but that was always `nil`, so we'd print out
`:0`.

Now, we construct a nice error message with the targeted port and
the ones we found.

The `--protocol` flag is also now case-insensitive to prevent any
weirdness/confusion there.

Co-authored-by: Nick Sieger <[email protected]>
Signed-off-by: Milas Bowman <[email protected]>
Milas Bowman 2 年之前
父節點
當前提交
053f20edab
共有 6 個文件被更改,包括 27 次插入10 次删除
  1. 1 0
      Makefile
  2. 5 3
      cmd/compose/port.go
  3. 1 1
      pkg/api/api.go
  4. 2 2
      pkg/api/proxy.go
  5. 17 3
      pkg/compose/port.go
  6. 1 1
      pkg/mocks/mock_docker_compose_api.go

+ 1 - 0
Makefile

@@ -77,6 +77,7 @@ build-and-e2e-compose-standalone: build e2e-compose-standalone ## Compile the co
 
 .PHONY: mocks
 mocks:
+	mockgen --version >/dev/null 2>&1 || go install github.com/golang/mock/[email protected]
 	mockgen -destination pkg/mocks/mock_docker_cli.go -package mocks github.com/docker/cli/cli/command Cli
 	mockgen -destination pkg/mocks/mock_docker_api.go -package mocks github.com/docker/docker/client APIClient
 	mockgen -destination pkg/mocks/mock_docker_compose_api.go -package mocks -source=./pkg/api/api.go Service

+ 5 - 3
cmd/compose/port.go

@@ -20,6 +20,7 @@ import (
 	"context"
 	"fmt"
 	"strconv"
+	"strings"
 
 	"github.com/spf13/cobra"
 
@@ -28,7 +29,7 @@ import (
 
 type portOptions struct {
 	*projectOptions
-	port     int
+	port     uint16
 	protocol string
 	index    int
 }
@@ -42,11 +43,12 @@ func portCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		Short: "Print the public port for a port binding.",
 		Args:  cobra.MinimumNArgs(2),
 		PreRunE: Adapt(func(ctx context.Context, args []string) error {
-			port, err := strconv.Atoi(args[1])
+			port, err := strconv.ParseUint(args[1], 10, 16)
 			if err != nil {
 				return err
 			}
-			opts.port = port
+			opts.port = uint16(port)
+			opts.protocol = strings.ToLower(opts.protocol)
 			return nil
 		}),
 		RunE: Adapt(func(ctx context.Context, args []string) error {

+ 1 - 1
pkg/api/api.go

@@ -72,7 +72,7 @@ type Service interface {
 	// Events executes the equivalent to a `compose events`
 	Events(ctx context.Context, projectName string, options EventsOptions) error
 	// Port executes the equivalent to a `compose port`
-	Port(ctx context.Context, projectName string, service string, port int, options PortOptions) (string, int, error)
+	Port(ctx context.Context, projectName string, service string, port uint16, options PortOptions) (string, int, error)
 	// Images executes the equivalent of a `compose images`
 	Images(ctx context.Context, projectName string, options ImagesOptions) ([]ImageSummary, error)
 }

+ 2 - 2
pkg/api/proxy.go

@@ -48,7 +48,7 @@ type ServiceProxy struct {
 	UnPauseFn            func(ctx context.Context, project string, options PauseOptions) error
 	TopFn                func(ctx context.Context, projectName string, services []string) ([]ContainerProcSummary, error)
 	EventsFn             func(ctx context.Context, project string, options EventsOptions) error
-	PortFn               func(ctx context.Context, project string, service string, port int, options PortOptions) (string, int, error)
+	PortFn               func(ctx context.Context, project string, service string, port uint16, options PortOptions) (string, int, error)
 	ImagesFn             func(ctx context.Context, projectName string, options ImagesOptions) ([]ImageSummary, error)
 	interceptors         []Interceptor
 }
@@ -294,7 +294,7 @@ func (s *ServiceProxy) Events(ctx context.Context, projectName string, options E
 }
 
 // Port implements Service interface
-func (s *ServiceProxy) Port(ctx context.Context, projectName string, service string, port int, options PortOptions) (string, int, error) {
+func (s *ServiceProxy) Port(ctx context.Context, projectName string, service string, port uint16, options PortOptions) (string, int, error) {
 	if s.PortFn == nil {
 		return "", 0, ErrNotImplemented
 	}

+ 17 - 3
pkg/compose/port.go

@@ -27,7 +27,7 @@ import (
 	"github.com/docker/docker/api/types/filters"
 )
 
-func (s *composeService) Port(ctx context.Context, projectName string, service string, port int, options api.PortOptions) (string, int, error) {
+func (s *composeService) Port(ctx context.Context, projectName string, service string, port uint16, options api.PortOptions) (string, int, error) {
 	projectName = strings.ToLower(projectName)
 	list, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
 		Filters: filters.NewArgs(
@@ -44,9 +44,23 @@ func (s *composeService) Port(ctx context.Context, projectName string, service s
 	}
 	container := list[0]
 	for _, p := range container.Ports {
-		if p.PrivatePort == uint16(port) && p.Type == options.Protocol {
+		if p.PrivatePort == port && p.Type == options.Protocol {
 			return p.IP, int(p.PublicPort), nil
 		}
 	}
-	return "", 0, err
+	return "", 0, portNotFoundError(options.Protocol, port, container)
+}
+
+func portNotFoundError(protocol string, port uint16, ctr moby.Container) error {
+	formatPort := func(protocol string, port uint16) string {
+		return fmt.Sprintf("%d/%s", port, protocol)
+	}
+
+	var containerPorts []string
+	for _, p := range ctr.Ports {
+		containerPorts = append(containerPorts, formatPort(p.Type, p.PublicPort))
+	}
+
+	name := strings.TrimPrefix(ctr.Names[0], "/")
+	return fmt.Errorf("no port %s for container %s: %s", formatPort(protocol, port), name, strings.Join(containerPorts, ", "))
 }

+ 1 - 1
pkg/mocks/mock_docker_compose_api.go

@@ -209,7 +209,7 @@ func (mr *MockServiceMockRecorder) Pause(ctx, projectName, options interface{})
 }
 
 // Port mocks base method.
-func (m *MockService) Port(ctx context.Context, projectName, service string, port int, options api.PortOptions) (string, int, error) {
+func (m *MockService) Port(ctx context.Context, projectName, service string, port uint16, options api.PortOptions) (string, int, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "Port", ctx, projectName, service, port, options)
 	ret0, _ := ret[0].(string)