1
0
Fork 0
mirror of https://github.com/arangodb/kube-arangodb.git synced 2024-12-15 17:51:03 +00:00
kube-arangodb/pkg/util/errors/errors.go

226 lines
4.9 KiB
Go

//
// DISCLAIMER
//
// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
package errors
import (
"context"
"fmt"
"io"
"net"
"net/url"
"os"
"syscall"
errs "github.com/pkg/errors"
driver "github.com/arangodb/go-driver"
"github.com/arangodb/kube-arangodb/pkg/logging"
)
var (
Cause = errs.Cause
New = errs.New
WithStack = errs.WithStack
Wrap = errs.Wrap
Wrapf = errs.Wrapf
WithMessage = errs.WithMessage
WithMessagef = errs.WithMessagef
)
// CauseWithNil returns Cause of an error.
// If error returned by Cause is same (no Causer interface implemented), function will return nil instead
func CauseWithNil(err error) error {
if nerr := Cause(err); err == nil {
return nil
} else if nerr == err {
// Cause returns same error if error object does not implement Causer interface
// To prevent infinite loops in usage CauseWithNil will return nil in this case
return nil
} else {
return nerr
}
}
func Newf(format string, args ...interface{}) error {
return New(fmt.Sprintf(format, args...))
}
type timeout interface {
Timeout() bool
}
// IsTimeout returns true if the given error is caused by a timeout error.
func IsTimeout(err error) bool {
if err == nil {
return false
}
if t, ok := errs.Cause(err).(timeout); ok {
return t.Timeout()
}
return false
}
type temporary interface {
Temporary() bool
}
// IsTemporary returns true if the given error is caused by a temporary error.
func IsTemporary(err error) bool {
if err == nil {
return false
}
if t, ok := errs.Cause(err).(temporary); ok {
return t.Temporary()
}
return false
}
// IsEOF returns true if the given error is caused by an EOF error.
func IsEOF(err error) bool {
err = errs.Cause(err)
if err == io.EOF {
return true
}
if ok, err := libCause(err); ok {
return IsEOF(err)
}
return false
}
// IsConnectionRefused returns true if the given error is caused by an "connection refused" error.
func IsConnectionRefused(err error) bool {
err = errs.Cause(err)
if err, ok := err.(syscall.Errno); ok {
return err == syscall.ECONNREFUSED
}
if ok, err := libCause(err); ok {
return IsConnectionRefused(err)
}
return false
}
// IsConnectionReset returns true if the given error is caused by an "connection reset by peer" error.
func IsConnectionReset(err error) bool {
err = errs.Cause(err)
if err, ok := err.(syscall.Errno); ok {
return err == syscall.ECONNRESET
}
if ok, err := libCause(err); ok {
return IsConnectionReset(err)
}
return false
}
// IsContextCanceled returns true if the given error is caused by a context cancelation.
func IsContextCanceled(err error) bool {
err = errs.Cause(err)
if err == context.Canceled {
return true
}
if ok, err := libCause(err); ok {
return IsContextCanceled(err)
}
return false
}
// IsContextDeadlineExpired returns true if the given error is caused by a context deadline expiration.
func IsContextDeadlineExpired(err error) bool {
err = errs.Cause(err)
if err == context.DeadlineExceeded {
return true
}
if ok, err := libCause(err); ok {
return IsContextDeadlineExpired(err)
}
return false
}
// IsContextCanceledOrExpired returns true if the given error is caused by a context cancelation
// or deadline expiration.
func IsContextCanceledOrExpired(err error) bool {
err = errs.Cause(err)
if err == context.Canceled || err == context.DeadlineExceeded {
return true
}
if ok, err := libCause(err); ok {
return IsContextCanceledOrExpired(err)
}
return false
}
// libCause returns the Cause of well known go library errors.
func libCause(err error) (bool, error) {
original := err
for {
switch e := err.(type) {
case *driver.ResponseError:
err = e.Err
case *net.DNSConfigError:
err = e.Err
case *net.OpError:
err = e.Err
case *os.SyscallError:
err = e.Err
case *url.Error:
err = e.Err
default:
return err != original, err
}
}
}
func LogError(logger logging.Logger, msg string, f func() error) {
if err := f(); err != nil {
logger.Err(err).Error(msg)
}
}
type Causer interface {
Cause() error
}
func IsReconcile(err error) bool {
if err == nil {
return false
}
if _, ok := err.(reconcile); ok {
return true
}
if c, ok := err.(Causer); ok {
return IsReconcile(c.Cause())
}
return false
}
func Reconcile() error {
return reconcile{}
}
type reconcile struct {
}
func (r reconcile) Error() string {
return "reconcile"
}