Merge pull request #81634 from likakuli/fix_errno

fixes a bug that connection refused error cannot be recognized correctly
This commit is contained in:
Kubernetes Prow Robot 2019-08-22 17:34:00 -07:00 committed by GitHub
commit 22a8bcf30a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 11 deletions

View File

@ -54,3 +54,20 @@ func IsConnectionReset(err error) bool {
} }
return false return false
} }
// Returns if the given err is "connection refused" error
func IsConnectionRefused(err error) bool {
if urlErr, ok := err.(*url.Error); ok {
err = urlErr.Err
}
if opErr, ok := err.(*net.OpError); ok {
err = opErr.Err
}
if osErr, ok := err.(*os.SyscallError); ok {
err = osErr.Err
}
if errno, ok := err.(syscall.Errno); ok && errno == syscall.ECONNREFUSED {
return true
}
return false
}

View File

@ -18,6 +18,9 @@ package net
import ( import (
"net" "net"
"net/url"
"os"
"syscall"
"testing" "testing"
) )
@ -66,3 +69,28 @@ func TestIPNetEqual(t *testing.T) {
} }
} }
} }
func TestIsConnectionRefused(t *testing.T) {
testCases := []struct {
err error
expect bool
}{
{
&url.Error{Err: &net.OpError{Err: syscall.ECONNRESET}},
false,
},
{
&url.Error{Err: &net.OpError{Err: syscall.ECONNREFUSED}},
true,
},
{&url.Error{Err: &net.OpError{Err: &os.SyscallError{Err: syscall.ECONNREFUSED}}},
true,
},
}
for _, tc := range testCases {
if result := IsConnectionRefused(tc.err); result != tc.expect {
t.Errorf("Expect to be %v, but actual is %v", tc.expect, result)
}
}
}

View File

@ -76,6 +76,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/naming:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/naming:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",

View File

@ -22,11 +22,8 @@ import (
"fmt" "fmt"
"io" "io"
"math/rand" "math/rand"
"net"
"net/url"
"reflect" "reflect"
"sync" "sync"
"syscall"
"time" "time"
apierrs "k8s.io/apimachinery/pkg/api/errors" apierrs "k8s.io/apimachinery/pkg/api/errors"
@ -35,6 +32,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/clock" "k8s.io/apimachinery/pkg/util/clock"
"k8s.io/apimachinery/pkg/util/naming" "k8s.io/apimachinery/pkg/util/naming"
utilnet "k8s.io/apimachinery/pkg/util/net"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
@ -285,14 +283,10 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
// It doesn't make sense to re-list all objects because most likely we will be able to restart // It doesn't make sense to re-list all objects because most likely we will be able to restart
// watch where we ended. // watch where we ended.
// If that's the case wait and resend watch request. // If that's the case wait and resend watch request.
if urlError, ok := err.(*url.Error); ok { if utilnet.IsConnectionRefused(err) {
if opError, ok := urlError.Err.(*net.OpError); ok {
if errno, ok := opError.Err.(syscall.Errno); ok && errno == syscall.ECONNREFUSED {
time.Sleep(time.Second) time.Sleep(time.Second)
continue continue
} }
}
}
return nil return nil
} }

View File

@ -24,7 +24,7 @@ import (
"testing" "testing"
"time" "time"
v1 "k8s.io/api/core/v1" "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"