Skip to content

Commit d8fd11d

Browse files
feat: use websockets for port forwards (#3717)
Signed-off-by: Austin Abro <[email protected]>
1 parent 8825dc0 commit d8fd11d

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

src/pkg/cluster/tunnel.go

+21-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
corev1 "k8s.io/api/core/v1"
1818
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
19+
"k8s.io/apimachinery/pkg/util/httpstream"
1920
"k8s.io/client-go/kubernetes"
2021
"k8s.io/client-go/rest"
2122
"k8s.io/client-go/tools/portforward"
@@ -456,12 +457,10 @@ func (tunnel *Tunnel) establish(ctx context.Context) (string, error) {
456457

457458
l.Debug("using URL to create portforward", "url", portForwardCreateURL)
458459

459-
// Construct the spdy client required by the client-go portforward library.
460-
transport, upgrader, err := spdy.RoundTripperFor(tunnel.restConfig)
460+
dialer, err := createDialer("POST", portForwardCreateURL, tunnel.restConfig)
461461
if err != nil {
462-
return "", fmt.Errorf("unable to create the spdy client %w", err)
462+
return "", fmt.Errorf("unable to create the dialer %w", err)
463463
}
464-
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", portForwardCreateURL)
465464

466465
// Construct a new PortForwarder struct that manages the instructed port forward tunnel.
467466
ports := []string{fmt.Sprintf("%d:%d", localPort, tunnel.remotePort)}
@@ -530,3 +529,21 @@ func (tunnel *Tunnel) getAttachablePodForService(ctx context.Context) (string, e
530529
}
531530
return podList.Items[0].Name, nil
532531
}
532+
533+
// Inspired by https://github.com/kubernetes/kubernetes/blob/680ea07dbb2c6050d13b93660fa4d27d2d28d6eb/staging/src/k8s.io/kubectl/pkg/cmd/portforward/portforward.go#L139-L156
534+
func createDialer(method string, url *url.URL, config *rest.Config) (httpstream.Dialer, error) {
535+
transport, upgrader, err := spdy.RoundTripperFor(config)
536+
if err != nil {
537+
return nil, err
538+
}
539+
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, method, url)
540+
tunnelingDialer, err := portforward.NewSPDYOverWebsocketDialer(url, config)
541+
if err != nil {
542+
return nil, err
543+
}
544+
// First attempt tunneling (websocket) dialer, then fallback to spdy dialer.
545+
dialer = portforward.NewFallbackDialer(tunnelingDialer, dialer, func(err error) bool {
546+
return httpstream.IsUpgradeFailure(err) || httpstream.IsHTTPSProxyError(err)
547+
})
548+
return dialer, nil
549+
}

0 commit comments

Comments
 (0)