From a9084923f2bd499c287b675007cb7c6c093d60ad Mon Sep 17 00:00:00 2001 From: Mike Lundy Date: Thu, 16 Aug 2018 13:11:26 -0700 Subject: [PATCH] export a method to expose which ports were forwarded Without this change, the only method to discover what local port was bound (if port 0 was requested) is to parse it out of the "out" stream, which isn't the most reliable method. --- .../client-go/tools/portforward/portforward.go | 17 +++++++++++++++++ .../tools/portforward/portforward_test.go | 13 +++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/staging/src/k8s.io/client-go/tools/portforward/portforward.go b/staging/src/k8s.io/client-go/tools/portforward/portforward.go index 9d7936e7c5f..bc6f43d7d15 100644 --- a/staging/src/k8s.io/client-go/tools/portforward/portforward.go +++ b/staging/src/k8s.io/client-go/tools/portforward/portforward.go @@ -340,3 +340,20 @@ func (pf *PortForwarder) Close() { } } } + +// GetPorts will return the ports that were forwarded; this can be used to +// retrieve the locally-bound port in cases where the input was port 0. This +// function will signal an error if the Ready channel is nil or if the +// listeners are not ready yet; this function will succeed after the Ready +// channel has been closed. +func (pf *PortForwarder) GetPorts() ([]ForwardedPort, error) { + if pf.Ready == nil { + return nil, fmt.Errorf("no Ready channel provided") + } + select { + case <-pf.Ready: + return pf.ports, nil + default: + return nil, fmt.Errorf("listeners not ready") + } +} diff --git a/staging/src/k8s.io/client-go/tools/portforward/portforward_test.go b/staging/src/k8s.io/client-go/tools/portforward/portforward_test.go index 2abbf16f29a..c1dd70b3e5e 100644 --- a/staging/src/k8s.io/client-go/tools/portforward/portforward_test.go +++ b/staging/src/k8s.io/client-go/tools/portforward/portforward_test.go @@ -99,8 +99,17 @@ func TestParsePortsAndNew(t *testing.T) { if dialer.dialed { t.Fatalf("%d: expected not dialed", i) } - if e, a := test.expected, pf.ports; !reflect.DeepEqual(e, a) { - t.Fatalf("%d: ports: expected %#v, got %#v", i, e, a) + if _, portErr := pf.GetPorts(); portErr == nil { + t.Fatalf("%d: GetPorts: error expected but got nil", i) + } + + // mock-signal the Ready channel + close(readyChan) + + if ports, portErr := pf.GetPorts(); portErr != nil { + t.Fatalf("%d: GetPorts: unable to retrieve ports: %s", i, portErr) + } else if !reflect.DeepEqual(test.expected, ports) { + t.Fatalf("%d: ports: expected %#v, got %#v", i, test.expected, ports) } if e, a := expectedStopChan, pf.stopChan; e != a { t.Fatalf("%d: stopChan: expected %#v, got %#v", i, e, a)