diff --git a/pkg/client/portforward/portforward.go b/pkg/client/portforward/portforward.go index 73d39dfcfaa..de7b5882d76 100644 --- a/pkg/client/portforward/portforward.go +++ b/pkg/client/portforward/portforward.go @@ -183,17 +183,26 @@ func (pf *PortForwarder) forward() error { return nil } -// listenOnPort delegates listener creation and waits for new connections -// in the background. +// listenOnPort delegates tcp4 and tcp6 listener creation and waits for connections on both of these addresses. +// If both listener creation fail, an error is raised. func (pf *PortForwarder) listenOnPort(port *ForwardedPort) error { - listener, err := pf.getListener("tcp", "localhost", port) + errTcp4 := pf.listenOnPortAndAddress(port, "tcp4", "127.0.0.1") + errTcp6 := pf.listenOnPortAndAddress(port, "tcp6", "[::1]") + if errTcp4 != nil && errTcp6 != nil { + return fmt.Errorf("All listeners failed to create with the following errors: %s, %s", errTcp4, errTcp6) + } + return nil +} + +// listenOnPortAndAddress delegates listener creation and waits for new connections +// in the background f +func (pf *PortForwarder) listenOnPortAndAddress(port *ForwardedPort, protocol string, address string) error { + listener, err := pf.getListener(protocol, address, port) if err != nil { return err } pf.listeners = append(pf.listeners, listener) - go pf.waitForConnection(listener, *port) - return nil } @@ -213,7 +222,7 @@ func (pf *PortForwarder) getListener(protocol string, hostname string, port *For return nil, fmt.Errorf("Error parsing local port: %s from %s (%s)", err, listenerAddress, host) } port.Local = uint16(localPortUInt) - glog.Infof("Forwarding from %d -> %d", localPortUInt, port.Remote) + glog.Infof("Forwarding from %s:%d -> %d", hostname, localPortUInt, port.Remote) return listener, nil } diff --git a/pkg/client/portforward/portforward_test.go b/pkg/client/portforward/portforward_test.go index 29f0a826c02..d9474e926a8 100644 --- a/pkg/client/portforward/portforward_test.go +++ b/pkg/client/portforward/portforward_test.go @@ -209,7 +209,7 @@ func (s *fakeUpgradeStream) Headers() http.Header { return http.Header{} } -type TestCase struct { +type GetListenerTestCase struct { Hostname string Protocol string ShouldRaiseError bool @@ -218,7 +218,7 @@ type TestCase struct { func TestGetListener(t *testing.T) { var pf PortForwarder - testCases := []TestCase{ + testCases := []GetListenerTestCase{ { Hostname: "localhost", Protocol: "tcp4", @@ -247,20 +247,12 @@ func TestGetListener(t *testing.T) { Protocol: "tcp6", ShouldRaiseError: true, }, - } - - // On some linux systems, ::1 does not resolve to localhost but to localhost6 or - // ip6-localhost. To make the test case portable, we need to do a reverse lookup on ::1 and - // trying to bind a port with the name. - names, err := net.LookupAddr("::1") - if err == nil && len(names) > 0 { - ipv6TestCase := TestCase{ - Hostname: names[0], - Protocol: "tcp6", - ShouldRaiseError: false, - ExpectedListenerAddress: "::1", - } - testCases = append(testCases, ipv6TestCase) + { + // IPv6 address must be put into brackets. This test reveals this. + Hostname: "::1", + Protocol: "tcp6", + ShouldRaiseError: true, + }, } for i, testCase := range testCases {