Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: pkg/errors is no longer maintained #7440

Merged
merged 12 commits into from
Mar 18, 2022
73 changes: 30 additions & 43 deletions errors/errors.go
Expand Up @@ -2,10 +2,8 @@ package errors

import (
"encoding/json"
"errors"
"fmt"
"io"

"github.com/pkg/errors"
)

// Externally visible error codes
Expand All @@ -24,30 +22,21 @@ const (
type ArgoError interface {
Error() string
Code() string
Message() string
JSON() []byte
StackTrace() errors.StackTrace
Format(s fmt.State, verb rune)
}

// argoerr is the internal implementation of an Argo error which wraps the error from pkg/errors
type argoerr struct {
code string
message string
stracer stackTracer
}

// stackTracer is interface for error types that have a stack trace
type stackTracer interface {
Error() string
StackTrace() errors.StackTrace
err error
}

// New returns an error with the supplied message.
// New also records the stack trace at the point it was called.
func New(code string, message string) error {
err := errors.New(message)
return argoerr{code, message, err.(stackTracer)}
return argoerr{code, message, err}
}

// Errorf returns an error and formats according to a format specifier
Expand Down Expand Up @@ -85,8 +74,8 @@ func Wrap(err error, code string, message string) error {
if err == nil {
return nil
}
err = errors.Wrap(err, message)
return argoerr{code, message, err.(stackTracer)}
err = fmt.Errorf(message+": %w", err)
return argoerr{code, message, err}
}

// Cause returns the underlying cause of the error, if possible.
Expand All @@ -102,25 +91,41 @@ func Wrap(err error, code string, message string) error {
// investigation.
func Cause(err error) error {
if argoErr, ok := err.(argoerr); ok {
return errors.Cause(argoErr.stracer)
return unwrapCauseArgoErr(argoErr.err)
}
return errors.Cause(err)
return unwrapCause(err)
}

func (e argoerr) Error() string {
return e.message
func unwrapCauseArgoErr(err error) error {
innerErr := errors.Unwrap(err)
for innerErr != nil {
err = innerErr
innerErr = errors.Unwrap(err)
}
return err
}

func (e argoerr) Code() string {
return e.code
func unwrapCause(err error) error {
type causer interface {
Cause() error
}

for err != nil {
cause, ok := err.(causer)
if !ok {
break
}
err = cause.Cause()
}
return err
}

func (e argoerr) Message() string {
func (e argoerr) Error() string {
return e.message
}

func (e argoerr) StackTrace() errors.StackTrace {
return e.stracer.StackTrace()
func (e argoerr) Code() string {
return e.code
}

func (e argoerr) JSON() []byte {
Expand All @@ -133,24 +138,6 @@ func (e argoerr) JSON() []byte {
return j
}

func (e argoerr) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
_, _ = io.WriteString(s, e.Error())
for _, pc := range e.StackTrace() {
fmt.Fprintf(s, "\n%+v", pc)
}
return
}
fallthrough
case 's':
_, _ = io.WriteString(s, e.Error())
case 'q':
fmt.Fprintf(s, "%q", e.Error())
}
}

// IsCode is a helper to determine if the error is of a specific code
func IsCode(code string, err error) bool {
if argoErr, ok := err.(argoerr); ok {
Expand Down
14 changes: 0 additions & 14 deletions errors/errors_test.go
Expand Up @@ -4,17 +4,11 @@ import (
"fmt"
"testing"

pkgerr "github.com/pkg/errors"
"github.com/stretchr/testify/assert"

"github.com/argoproj/argo-workflows/v3/errors"
)

// stackTracer is interface for error types that have a stack trace
type stackTracer interface {
StackTrace() pkgerr.StackTrace
}

// TestErrorf tests the initializer of error package
func TestErrorf(t *testing.T) {
err := errors.Errorf(errors.CodeInternal, "test internal")
Expand All @@ -38,17 +32,9 @@ func TestInternalError(t *testing.T) {
// Test wrapping errors
err = fmt.Errorf("random error")
intWrap := errors.InternalWrapError(err)
_ = intWrap.(stackTracer)
assert.Equal(t, "random error", intWrap.Error())
intWrap = errors.InternalWrapError(err, "different message")
_ = intWrap.(stackTracer)
assert.Equal(t, "different message", intWrap.Error())
intWrap = errors.InternalWrapErrorf(err, "hello %s", "world")
_ = intWrap.(stackTracer)
assert.Equal(t, "hello world", intWrap.Error())
}

func TestStackTrace(t *testing.T) {
err := errors.New("MYCODE", "my message")
assert.Contains(t, fmt.Sprintf("%+v", err), "errors_test.go")
}
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -36,7 +36,6 @@ require (
github.com/klauspost/pgzip v1.2.5
github.com/minio/minio-go/v7 v7.0.2
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.11.0
github.com/prometheus/client_model v0.2.0
github.com/prometheus/common v0.26.0
Expand Down Expand Up @@ -149,6 +148,7 @@ require (
github.com/onsi/ginkgo v1.16.4 // indirect
github.com/onsi/gomega v1.13.0 // indirect
github.com/pelletier/go-toml v1.9.3 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
Expand Down
14 changes: 7 additions & 7 deletions util/kubeconfig/kubeconfig.go
Expand Up @@ -2,6 +2,7 @@ package kubeconfig

import (
"encoding/base64"
goErrors "errors"
stephpalis marked this conversation as resolved.
Show resolved Hide resolved
"fmt"
"io/ioutil"
"net/http"
Expand All @@ -10,7 +11,6 @@ import (
"strings"
"time"

"github.com/pkg/errors"
clientauthenticationapi "k8s.io/client-go/pkg/apis/clientauthentication"
"k8s.io/client-go/plugin/pkg/client/auth/exec"
restclient "k8s.io/client-go/rest"
Expand Down Expand Up @@ -43,15 +43,15 @@ func GetRestConfig(token string) (*restclient.Config, error) {
token = strings.TrimSpace(strings.TrimPrefix(token, BasicAuthScheme))
username, password, ok := decodeBasicAuthToken(token)
if !ok {
return nil, errors.New("Error parsing Basic Authentication")
return nil, goErrors.New("Error parsing Basic Authentication")
}
return GetBasicRestConfig(username, password)
}
if IsBearerAuthScheme(token) {
token = strings.TrimSpace(strings.TrimPrefix(token, BearerAuthScheme))
return GetBearerRestConfig(token)
}
return nil, errors.New("Unsupported authentication scheme")
return nil, goErrors.New("Unsupported authentication scheme")
}

// convert a basic token (username, password) into a REST config
Expand Down Expand Up @@ -127,7 +127,7 @@ func GetAuthString(in *restclient.Config, explicitKubeConfigPath string) (string

func GetBasicAuthToken(in *restclient.Config) (string, error) {
if in == nil {
return "", errors.Errorf("RestClient can't be nil")
return "", fmt.Errorf("RestClient can't be nil")
}

return encodeBasicAuthToken(in.Username, in.Password), nil
Expand All @@ -140,7 +140,7 @@ func GetBearerToken(in *restclient.Config, explicitKubeConfigPath string) (strin
}

if in == nil {
return "", errors.Errorf("RestClient can't be nil")
return "", fmt.Errorf("RestClient can't be nil")
}
if in.ExecProvider != nil {
tc, err := in.TransportConfig()
Expand Down Expand Up @@ -194,7 +194,7 @@ func GetBearerToken(in *restclient.Config, explicitKubeConfigPath string) (strin
return strings.TrimPrefix(token, "Bearer "), nil
}
}
return "", errors.Errorf("could not find a token")
return "", fmt.Errorf("could not find a token")
}

/*https://pkg.go.dev/k8s.io/client-go@v0.20.4/pkg/apis/clientauthentication#Cluster
Expand Down Expand Up @@ -281,7 +281,7 @@ func RefreshTokenIfExpired(restConfig *restclient.Config, explicitPath, curentTo
if timestr != "" {
t, err := time.Parse(time.RFC3339, timestr)
if err != nil {
return "", errors.Errorf("Invalid expiry date in Kubeconfig. %v", err)
return "", fmt.Errorf("Invalid expiry date in Kubeconfig. %v", err)
}
if time.Now().After(t) {
err = RefreshAuthToken(restConfig)
Expand Down