mirror of
https://github.com/kubernetes/client-go.git
synced 2025-09-03 16:16:06 +00:00
Clean error handling in port-forward
This commit introduces: 1. Cleanups in port-forwarding error handling code, which ensures that we only compare lowercased text always. 2. E2E verifying that when a pod is removed a port-forward is stopped. Signed-off-by: Maciej Szulik <soltysh@gmail.com> Kubernetes-commit: 0b1617ccefbc6ea61c0e7c2b0b4052703f11c51c
This commit is contained in:
committed by
Kubernetes Publisher
parent
d6404c8d76
commit
bf414551df
@@ -37,7 +37,13 @@ import (
|
|||||||
// TODO move to API machinery and re-unify with kubelet/server/portfoward
|
// TODO move to API machinery and re-unify with kubelet/server/portfoward
|
||||||
const PortForwardProtocolV1Name = "portforward.k8s.io"
|
const PortForwardProtocolV1Name = "portforward.k8s.io"
|
||||||
|
|
||||||
var ErrLostConnectionToPod = errors.New("lost connection to pod")
|
var (
|
||||||
|
// error returned whenever we lost connection to a pod
|
||||||
|
ErrLostConnectionToPod = errors.New("lost connection to pod")
|
||||||
|
|
||||||
|
// set of error we're expecting during port-forwarding
|
||||||
|
networkClosedError = "use of closed network connection"
|
||||||
|
)
|
||||||
|
|
||||||
// PortForwarder knows how to listen for local connections and forward them to
|
// PortForwarder knows how to listen for local connections and forward them to
|
||||||
// a remote pod via an upgraded HTTP request.
|
// a remote pod via an upgraded HTTP request.
|
||||||
@@ -312,7 +318,7 @@ func (pf *PortForwarder) waitForConnection(listener net.Listener, port Forwarded
|
|||||||
conn, err := listener.Accept()
|
conn, err := listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO consider using something like https://github.com/hydrogen18/stoppableListener?
|
// TODO consider using something like https://github.com/hydrogen18/stoppableListener?
|
||||||
if !strings.Contains(strings.ToLower(err.Error()), "use of closed network connection") {
|
if !strings.Contains(strings.ToLower(err.Error()), networkClosedError) {
|
||||||
runtime.HandleError(fmt.Errorf("error accepting connection on port %d: %v", port.Local, err))
|
runtime.HandleError(fmt.Errorf("error accepting connection on port %d: %v", port.Local, err))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -381,7 +387,7 @@ func (pf *PortForwarder) handleConnection(conn net.Conn, port ForwardedPort) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// Copy from the remote side to the local port.
|
// Copy from the remote side to the local port.
|
||||||
if _, err := io.Copy(conn, dataStream); err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
|
if _, err := io.Copy(conn, dataStream); err != nil && !strings.Contains(strings.ToLower(err.Error()), networkClosedError) {
|
||||||
runtime.HandleError(fmt.Errorf("error copying from remote stream to local connection: %v", err))
|
runtime.HandleError(fmt.Errorf("error copying from remote stream to local connection: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +400,7 @@ func (pf *PortForwarder) handleConnection(conn net.Conn, port ForwardedPort) {
|
|||||||
defer dataStream.Close()
|
defer dataStream.Close()
|
||||||
|
|
||||||
// Copy from the local port to the remote side.
|
// Copy from the local port to the remote side.
|
||||||
if _, err := io.Copy(dataStream, conn); err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
|
if _, err := io.Copy(dataStream, conn); err != nil && !strings.Contains(strings.ToLower(err.Error()), networkClosedError) {
|
||||||
runtime.HandleError(fmt.Errorf("error copying from local connection to remote stream: %v", err))
|
runtime.HandleError(fmt.Errorf("error copying from local connection to remote stream: %v", err))
|
||||||
// break out of the select below without waiting for the other copy to finish
|
// break out of the select below without waiting for the other copy to finish
|
||||||
close(localError)
|
close(localError)
|
||||||
@@ -406,10 +412,10 @@ func (pf *PortForwarder) handleConnection(conn net.Conn, port ForwardedPort) {
|
|||||||
case <-remoteDone:
|
case <-remoteDone:
|
||||||
case <-localError:
|
case <-localError:
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
reset dataStream to discard any unsent data, preventing port forwarding from being blocked.
|
// reset dataStream to discard any unsent data, preventing port forwarding from being blocked.
|
||||||
we must reset dataStream before waiting on errorChan, otherwise, the blocking data will affect errorStream and cause <-errorChan to block indefinitely.
|
// we must reset dataStream before waiting on errorChan, otherwise,
|
||||||
*/
|
// the blocking data will affect errorStream and cause <-errorChan to block indefinitely.
|
||||||
_ = dataStream.Reset()
|
_ = dataStream.Reset()
|
||||||
|
|
||||||
// always expect something on errorChan (it may be nil)
|
// always expect something on errorChan (it may be nil)
|
||||||
|
Reference in New Issue
Block a user