From e73fa4a1861bfc607efda0a1e00a28152e58e24a Mon Sep 17 00:00:00 2001 From: Abu Kashem Date: Wed, 10 Jun 2020 16:20:37 -0400 Subject: [PATCH] retry on 'unexpected EOF' error 'unexpected EOF' is usually a transient error. client-go request uses IsProbableEOF to determine whether it is going to retry a failed request. --- .../k8s.io/apimachinery/pkg/util/net/http.go | 2 + .../apimachinery/pkg/util/net/http_test.go | 63 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/staging/src/k8s.io/apimachinery/pkg/util/net/http.go b/staging/src/k8s.io/apimachinery/pkg/util/net/http.go index 8ac4b1f8d16..3c097f0eef2 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/net/http.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/net/http.go @@ -83,6 +83,8 @@ func IsProbableEOF(err error) bool { switch { case err == io.EOF: return true + case err == io.ErrUnexpectedEOF: + return true case msg == "http: can't write HTTP request on broken connection": return true case strings.Contains(msg, "http2: server sent GOAWAY and closed the connection"): diff --git a/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go b/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go index cd4f7f743ea..002c1884ba8 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/net/http_test.go @@ -23,6 +23,7 @@ import ( "bytes" "crypto/tls" "fmt" + "io" "io/ioutil" "net" "net/http" @@ -1008,3 +1009,65 @@ func TestParseWarningHeaders(t *testing.T) { }) } } + +func TestIsProbableEOF(t *testing.T) { + tests := []struct { + name string + err error + expected bool + }{ + { + name: "with no error", + expected: false, + }, + { + name: "with EOF error", + err: io.EOF, + expected: true, + }, + { + name: "with unexpected EOF error", + err: io.ErrUnexpectedEOF, + expected: true, + }, + { + name: "with broken connection error", + err: fmt.Errorf("http: can't write HTTP request on broken connection"), + expected: true, + }, + { + name: "with server sent GOAWAY error", + err: fmt.Errorf("error foo - http2: server sent GOAWAY and closed the connection - error bar"), + expected: true, + }, + { + name: "with connection reset by peer error", + err: fmt.Errorf("error foo - connection reset by peer - error bar"), + expected: true, + }, + { + name: "with use of closed network connection error", + err: fmt.Errorf("error foo - Use of closed network connection - error bar"), + expected: true, + }, + { + name: "with url error", + err: &url.Error{ + Err: io.ErrUnexpectedEOF, + }, + expected: true, + }, + { + name: "with unrecognized error", + err: fmt.Errorf("error foo"), + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actual := IsProbableEOF(test.err) + assert.Equal(t, test.expected, actual) + }) + } +}