mirror of https://github.com/k3s-io/k3s
client-go: Dynamic local port not accessible when port-forwarding
When setting up a port forwarding with the client-go library (using the `k8s.io/client-go/tools/portforward.PortForwarder`) with a non-defined local port (i.e. passing `:80` as `ports` parameter to `portforward.New(...)`), a local port will be assigned dynamically. Currently, the local port will be _always_ 0 if it was not specified initially. This is because the assigned local port is only set on a _copy_ of the actual `ForwardedPort` type that is obtained in a `range` loop. This PR changes this behaviour to set the local port at the correct instance by passing a pointer instead of a copy to the relevant functions.pull/564/head
parent
cdfb9126d3
commit
bbddd27f0d
|
@ -197,8 +197,9 @@ func (pf *PortForwarder) forward() error {
|
|||
var err error
|
||||
|
||||
listenSuccess := false
|
||||
for _, port := range pf.ports {
|
||||
err = pf.listenOnPort(&port)
|
||||
for i := range pf.ports {
|
||||
port := &pf.ports[i]
|
||||
err = pf.listenOnPort(port)
|
||||
switch {
|
||||
case err == nil:
|
||||
listenSuccess = true
|
||||
|
|
|
@ -18,11 +18,13 @@ package portforward
|
|||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/httpstream"
|
||||
)
|
||||
|
@ -39,6 +41,37 @@ func (d *fakeDialer) Dial(protocols ...string) (httpstream.Connection, string, e
|
|||
return d.conn, d.negotiatedProtocol, d.err
|
||||
}
|
||||
|
||||
type fakeConnection struct {
|
||||
closed bool
|
||||
closeChan chan bool
|
||||
}
|
||||
|
||||
func newFakeConnection() httpstream.Connection {
|
||||
return &fakeConnection{
|
||||
closeChan: make(chan bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *fakeConnection) CreateStream(headers http.Header) (httpstream.Stream, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *fakeConnection) Close() error {
|
||||
if !c.closed {
|
||||
c.closed = true
|
||||
close(c.closeChan)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *fakeConnection) CloseChan() <-chan bool {
|
||||
return c.closeChan
|
||||
}
|
||||
|
||||
func (c *fakeConnection) SetIdleTimeout(timeout time.Duration) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
func TestParsePortsAndNew(t *testing.T) {
|
||||
tests := []struct {
|
||||
input []string
|
||||
|
@ -254,3 +287,46 @@ func TestGetListener(t *testing.T) {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPortsReturnsDynamicallyAssignedLocalPort(t *testing.T) {
|
||||
dialer := &fakeDialer{
|
||||
conn: newFakeConnection(),
|
||||
}
|
||||
|
||||
stopChan := make(chan struct{})
|
||||
readyChan := make(chan struct{})
|
||||
errChan := make(chan error)
|
||||
|
||||
defer func() {
|
||||
close(stopChan)
|
||||
|
||||
forwardErr := <-errChan
|
||||
if forwardErr != nil {
|
||||
t.Fatalf("ForwardPorts returned error: %s", forwardErr)
|
||||
}
|
||||
}()
|
||||
|
||||
pf, err := New(dialer, []string{":5000"}, stopChan, readyChan, os.Stdout, os.Stderr)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error while calling New: %s", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
errChan <- pf.ForwardPorts()
|
||||
close(errChan)
|
||||
}()
|
||||
|
||||
<-pf.Ready
|
||||
|
||||
ports, err := pf.GetPorts()
|
||||
|
||||
if len(ports) != 1 {
|
||||
t.Fatalf("expected 1 port, got %d", len(ports))
|
||||
}
|
||||
|
||||
port := ports[0]
|
||||
if port.Local == 0 {
|
||||
t.Fatalf("local port is 0, expected != 0")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue