Skip to content

Commit

Permalink
Add IsTransientErr function
Browse files Browse the repository at this point in the history
Checks if an error from an API server request is a transient server
issue such that a retry might succeed.

Signed-off-by: Tom Pantelis <[email protected]>
  • Loading branch information
tpantelis committed May 29, 2024
1 parent b03ab79 commit 216f2c6
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
8 changes: 8 additions & 0 deletions pkg/resource/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package resource

import (
"errors"
"net"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
Expand Down Expand Up @@ -68,3 +69,10 @@ func ExtractMissingNamespaceFromErr(err error) string {

return d.Name
}

func IsTransientErr(err error) bool {
// Check for errors indicating the server is temporarily busy (ServerTimeout and TooManyRequests). Also check for
// a net.OpError indicating a network connectivity issue. This is typically wrapped by a url.Error.
var netError *net.OpError
return apierrors.IsServerTimeout(err) || apierrors.IsTooManyRequests(err) || errors.As(err, &netError)
}
48 changes: 47 additions & 1 deletion pkg/resource/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ limitations under the License.
package resource_test

import (
"errors"
"net"
"net/url"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/pkg/errors"
"github.com/submariner-io/admiral/pkg/resource"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
Expand Down Expand Up @@ -93,3 +95,47 @@ var _ = Describe("IsMissingNamespaceErr and ExtractMissingNamespaceFromErr", fun
})
})
})

var _ = Describe("IsTransientErr", func() {
When("the error is ServerTimeout", func() {
It("should return true", func() {
Expect(resource.IsTransientErr(apierrors.NewServerTimeout(schema.GroupResource{}, "get", 5))).To(BeTrue())
})
})

When("the error is TooManyRequests", func() {
It("should return true", func() {
Expect(resource.IsTransientErr(apierrors.NewTooManyRequests("", 5))).To(BeTrue())
})
})

When("the error is a wrapped network operation failure", func() {
It("should return true", func() {
Expect(resource.IsTransientErr(errors.Wrap(&url.Error{
Op: "Get",
URL: "https://192.168.67.2:8443/api/v1/namespaces",
Err: &net.OpError{
Op: "dial",
Net: "tcp",
Addr: &net.TCPAddr{
IP: net.IP{192, 168, 67, 2},
Port: 8443,
},
Err: &net.DNSError{},
},
}, "wrapped"))).To(BeTrue())
})
})

When("the error is not transient", func() {
It("should return false", func() {
Expect(resource.IsTransientErr(apierrors.NewBadRequest(""))).To(BeFalse())
})
})

When("the error is nil", func() {
It("should return false", func() {
Expect(resource.IsTransientErr(nil)).To(BeFalse())
})
})
})

0 comments on commit 216f2c6

Please sign in to comment.