-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Kimmo Lehto <klehto@mirantis.com> Better error design and usable error categories, such as ErrCantConnect which is a clear indicator that Connect() should not be retried. The oddly specific single-use errors are now wrapped under more meaningful top level errors.
- Loading branch information
Showing
27 changed files
with
408 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package rig | ||
|
||
import ( | ||
"github.com/k0sproject/rig/errstring" | ||
) | ||
|
||
var ( | ||
ErrOS = errstring.New("local os") // ErrOS is returned when an action fails on local OS | ||
ErrInvalidPath = errstring.New("invalid path") // ErrInvalidPath is returned when a path is invalid | ||
ErrValidationFailed = errstring.New("validation failed") // ErrValidationFailed is returned when a validation fails | ||
ErrSudoRequired = errstring.New("sudo required") // ErrSudoRequired is returned when sudo is required | ||
ErrNotFound = errstring.New("not found") // ErrNotFound is returned when a resource is not found | ||
ErrNotImplemented = errstring.New("not implemented") // ErrNotImplemented is returned when a feature is not implemented | ||
ErrNotSupported = errstring.New("not supported") // ErrNotSupported is returned when a feature is not supported | ||
ErrAuthFailed = errstring.New("authentication failed") // ErrAuthFailed is returned when authentication fails | ||
ErrUploadFailed = errstring.New("upload failed") // ErrUploadFailed is returned when an upload fails | ||
ErrNotConnected = errstring.New("not connected") // ErrNotConnected is returned when a connection is not established | ||
ErrCantConnect = errstring.New("can't connect") // ErrCantConnect is returned when a connection is not established and retrying will fail | ||
ErrCommandFailed = errstring.New("command failed") // ErrCommandFailed is returned when a command fails | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package rig | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestErrorStringer(t *testing.T) { | ||
type testCase struct { | ||
name string | ||
err error | ||
expected string | ||
} | ||
|
||
for _, scenario := range []testCase{ | ||
{ | ||
name: "non-wrapped error", | ||
err: ErrOS, | ||
expected: "local os", | ||
}, | ||
{ | ||
name: "error wrapped in error", | ||
err: ErrOS.Wrap(ErrInvalidPath), | ||
expected: "local os: invalid path", | ||
}, | ||
{ | ||
name: "string wrapped error", | ||
err: ErrOS.Wrapf("test"), | ||
expected: "local os: test", | ||
}, | ||
{ | ||
name: "double wrapped string error", | ||
err: ErrOS.Wrapf("test: %w", ErrInvalidPath), | ||
expected: "local os: test: invalid path", | ||
}, | ||
} { | ||
t.Run(scenario.name, func(t *testing.T) { | ||
require.Error(t, scenario.err) | ||
require.Equal(t, scenario.expected, scenario.err.Error()) | ||
}) | ||
} | ||
} | ||
|
||
func TestUnwrap(t *testing.T) { | ||
err := ErrOS.Wrap(ErrInvalidPath) | ||
require.Equal(t, ErrInvalidPath, errors.Unwrap(err)) | ||
} | ||
|
||
func TestErrorsIs(t *testing.T) { | ||
err := ErrOS.Wrap(ErrInvalidPath.Wrap(ErrNotFound)) | ||
require.True(t, errors.Is(err, ErrOS)) | ||
require.True(t, errors.Is(err, ErrInvalidPath)) | ||
require.True(t, errors.Is(err, ErrNotFound)) | ||
require.False(t, errors.Is(err, ErrNotConnected)) | ||
} | ||
|
||
type testErr struct { | ||
msg string | ||
} | ||
|
||
func (t *testErr) Error() string { | ||
return "foo " + t.msg | ||
} | ||
|
||
func TestErrorsAs(t *testing.T) { | ||
err := ErrOS.Wrap(ErrInvalidPath.Wrap(&testErr{msg: "test"})) | ||
var cmp *testErr | ||
require.True(t, errors.As(err, &cmp)) | ||
require.Equal(t, "local os: invalid path: foo test", err.Error()) | ||
if errors.As(err, &cmp) { | ||
require.Equal(t, "foo test", cmp.Error()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Package errstring defines a simple error struct | ||
package errstring | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
// Error is the base type for rig errors | ||
type Error struct { | ||
msg string | ||
} | ||
|
||
// Error implements the error interface | ||
func (e *Error) Error() string { | ||
return e.msg | ||
} | ||
|
||
func (e *Error) Unwrap() error { | ||
return nil | ||
} | ||
|
||
// New creates a new error | ||
func New(msg string) *Error { | ||
return &Error{msg} | ||
} | ||
|
||
// Wrap wraps another error with this error | ||
func (e *Error) Wrap(errB error) error { | ||
return &wrappedError{ | ||
errA: e, | ||
errB: errB, | ||
} | ||
} | ||
|
||
// Wrapf is a shortcut for Wrap(fmt.Errorf("...", ...)) | ||
func (e *Error) Wrapf(msg string, args ...any) error { | ||
return &wrappedError{ | ||
errA: e, | ||
errB: fmt.Errorf(msg, args...), //nolint:goerr113 | ||
} | ||
} | ||
|
||
type wrappedError struct { | ||
errA error | ||
errB error | ||
} | ||
|
||
func (e *wrappedError) Error() string { | ||
return e.errA.Error() + ": " + e.errB.Error() | ||
} | ||
|
||
func (e *wrappedError) Is(err error) bool { | ||
if err == nil { | ||
return false | ||
} | ||
return e.errA == err //nolint:goerr113 | ||
} | ||
|
||
func (e *wrappedError) Unwrap() error { | ||
return e.errB | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package exec | ||
|
||
import "github.com/k0sproject/rig/errstring" | ||
|
||
var ( | ||
ErrRemote = errstring.New("remote exec error") // ErrRemote is returned when an action fails on remote host | ||
ErrSudo = errstring.New("sudo error") // ErrSudo is returned when wrapping a command with sudo fails | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.