Remove unused pkg/errdefs package
Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
parent
fb9b59a843
commit
7cf54b437f
@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package errdefs defines the common errors used throughout containerd
|
|
||||||
// packages.
|
|
||||||
//
|
|
||||||
// Use with fmt.Errorf to add context to an error.
|
|
||||||
//
|
|
||||||
// To detect an error class, use the IsXXX functions to tell whether an error
|
|
||||||
// is of a certain type.
|
|
||||||
//
|
|
||||||
// The functions ToGRPC and FromGRPC can be used to map server-side and
|
|
||||||
// client-side errors to the correct types.
|
|
||||||
package errdefs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Definitions of common error types used throughout containerd. All containerd
|
|
||||||
// errors returned by most packages will map into one of these errors classes.
|
|
||||||
// Packages should return errors of these types when they want to instruct a
|
|
||||||
// client to take a particular action.
|
|
||||||
//
|
|
||||||
// For the most part, we just try to provide local grpc errors. Most conditions
|
|
||||||
// map very well to those defined by grpc.
|
|
||||||
var (
|
|
||||||
ErrUnknown = errors.New("unknown") // used internally to represent a missed mapping.
|
|
||||||
ErrInvalidArgument = errors.New("invalid argument")
|
|
||||||
ErrNotFound = errors.New("not found")
|
|
||||||
ErrAlreadyExists = errors.New("already exists")
|
|
||||||
ErrFailedPrecondition = errors.New("failed precondition")
|
|
||||||
ErrUnavailable = errors.New("unavailable")
|
|
||||||
ErrNotImplemented = errors.New("not implemented") // represents not supported and unimplemented
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsInvalidArgument returns true if the error is due to an invalid argument
|
|
||||||
func IsInvalidArgument(err error) bool {
|
|
||||||
return errors.Is(err, ErrInvalidArgument)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotFound returns true if the error is due to a missing object
|
|
||||||
func IsNotFound(err error) bool {
|
|
||||||
return errors.Is(err, ErrNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAlreadyExists returns true if the error is due to an already existing
|
|
||||||
// metadata item
|
|
||||||
func IsAlreadyExists(err error) bool {
|
|
||||||
return errors.Is(err, ErrAlreadyExists)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFailedPrecondition returns true if an operation could not proceed to the
|
|
||||||
// lack of a particular condition
|
|
||||||
func IsFailedPrecondition(err error) bool {
|
|
||||||
return errors.Is(err, ErrFailedPrecondition)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsUnavailable returns true if the error is due to a resource being unavailable
|
|
||||||
func IsUnavailable(err error) bool {
|
|
||||||
return errors.Is(err, ErrUnavailable)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotImplemented returns true if the error is due to not being implemented
|
|
||||||
func IsNotImplemented(err error) bool {
|
|
||||||
return errors.Is(err, ErrNotImplemented)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsCanceled returns true if the error is due to `context.Canceled`.
|
|
||||||
func IsCanceled(err error) bool {
|
|
||||||
return errors.Is(err, context.Canceled)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsDeadlineExceeded returns true if the error is due to
|
|
||||||
// `context.DeadlineExceeded`.
|
|
||||||
func IsDeadlineExceeded(err error) bool {
|
|
||||||
return errors.Is(err, context.DeadlineExceeded)
|
|
||||||
}
|
|
@ -1,147 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package errdefs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ToGRPC will attempt to map the backend containerd error into a grpc error,
|
|
||||||
// using the original error message as a description.
|
|
||||||
//
|
|
||||||
// Further information may be extracted from certain errors depending on their
|
|
||||||
// type.
|
|
||||||
//
|
|
||||||
// If the error is unmapped, the original error will be returned to be handled
|
|
||||||
// by the regular grpc error handling stack.
|
|
||||||
func ToGRPC(err error) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if isGRPCError(err) {
|
|
||||||
// error has already been mapped to grpc
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case IsInvalidArgument(err):
|
|
||||||
return status.Errorf(codes.InvalidArgument, err.Error())
|
|
||||||
case IsNotFound(err):
|
|
||||||
return status.Errorf(codes.NotFound, err.Error())
|
|
||||||
case IsAlreadyExists(err):
|
|
||||||
return status.Errorf(codes.AlreadyExists, err.Error())
|
|
||||||
case IsFailedPrecondition(err):
|
|
||||||
return status.Errorf(codes.FailedPrecondition, err.Error())
|
|
||||||
case IsUnavailable(err):
|
|
||||||
return status.Errorf(codes.Unavailable, err.Error())
|
|
||||||
case IsNotImplemented(err):
|
|
||||||
return status.Errorf(codes.Unimplemented, err.Error())
|
|
||||||
case IsCanceled(err):
|
|
||||||
return status.Errorf(codes.Canceled, err.Error())
|
|
||||||
case IsDeadlineExceeded(err):
|
|
||||||
return status.Errorf(codes.DeadlineExceeded, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToGRPCf maps the error to grpc error codes, assembling the formatting string
|
|
||||||
// and combining it with the target error string.
|
|
||||||
//
|
|
||||||
// This is equivalent to errdefs.ToGRPC(fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err))
|
|
||||||
func ToGRPCf(err error, format string, args ...interface{}) error {
|
|
||||||
return ToGRPC(fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err))
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromGRPC returns the underlying error from a grpc service based on the grpc error code
|
|
||||||
func FromGRPC(err error) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var cls error // divide these into error classes, becomes the cause
|
|
||||||
|
|
||||||
switch code(err) {
|
|
||||||
case codes.InvalidArgument:
|
|
||||||
cls = ErrInvalidArgument
|
|
||||||
case codes.AlreadyExists:
|
|
||||||
cls = ErrAlreadyExists
|
|
||||||
case codes.NotFound:
|
|
||||||
cls = ErrNotFound
|
|
||||||
case codes.Unavailable:
|
|
||||||
cls = ErrUnavailable
|
|
||||||
case codes.FailedPrecondition:
|
|
||||||
cls = ErrFailedPrecondition
|
|
||||||
case codes.Unimplemented:
|
|
||||||
cls = ErrNotImplemented
|
|
||||||
case codes.Canceled:
|
|
||||||
cls = context.Canceled
|
|
||||||
case codes.DeadlineExceeded:
|
|
||||||
cls = context.DeadlineExceeded
|
|
||||||
default:
|
|
||||||
cls = ErrUnknown
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := rebaseMessage(cls, err)
|
|
||||||
if msg != "" {
|
|
||||||
err = fmt.Errorf("%s: %w", msg, cls)
|
|
||||||
} else {
|
|
||||||
err = cls
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// rebaseMessage removes the repeats for an error at the end of an error
|
|
||||||
// string. This will happen when taking an error over grpc then remapping it.
|
|
||||||
//
|
|
||||||
// Effectively, we just remove the string of cls from the end of err if it
|
|
||||||
// appears there.
|
|
||||||
func rebaseMessage(cls error, err error) string {
|
|
||||||
desc := errDesc(err)
|
|
||||||
clss := cls.Error()
|
|
||||||
if desc == clss {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.TrimSuffix(desc, ": "+clss)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isGRPCError(err error) bool {
|
|
||||||
_, ok := status.FromError(err)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func code(err error) codes.Code {
|
|
||||||
if s, ok := status.FromError(err); ok {
|
|
||||||
return s.Code()
|
|
||||||
}
|
|
||||||
return codes.Unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
func errDesc(err error) string {
|
|
||||||
if s, ok := status.FromError(err); ok {
|
|
||||||
return s.Message()
|
|
||||||
}
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package errdefs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGRPCRoundTrip(t *testing.T) {
|
|
||||||
errShouldLeaveAlone := errors.New("unknown to package")
|
|
||||||
|
|
||||||
for _, testcase := range []struct {
|
|
||||||
input error
|
|
||||||
cause error
|
|
||||||
str string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: ErrAlreadyExists,
|
|
||||||
cause: ErrAlreadyExists,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: ErrNotFound,
|
|
||||||
cause: ErrNotFound,
|
|
||||||
},
|
|
||||||
//nolint:dupword
|
|
||||||
{
|
|
||||||
input: fmt.Errorf("test test test: %w", ErrFailedPrecondition),
|
|
||||||
cause: ErrFailedPrecondition,
|
|
||||||
str: "test test test: failed precondition",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: status.Errorf(codes.Unavailable, "should be not available"),
|
|
||||||
cause: ErrUnavailable,
|
|
||||||
str: "should be not available: unavailable",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: errShouldLeaveAlone,
|
|
||||||
cause: ErrUnknown,
|
|
||||||
str: errShouldLeaveAlone.Error() + ": " + ErrUnknown.Error(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: context.Canceled,
|
|
||||||
cause: context.Canceled,
|
|
||||||
str: "context canceled",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: fmt.Errorf("this is a test cancel: %w", context.Canceled),
|
|
||||||
cause: context.Canceled,
|
|
||||||
str: "this is a test cancel: context canceled",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: context.DeadlineExceeded,
|
|
||||||
cause: context.DeadlineExceeded,
|
|
||||||
str: "context deadline exceeded",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: fmt.Errorf("this is a test deadline exceeded: %w", context.DeadlineExceeded),
|
|
||||||
cause: context.DeadlineExceeded,
|
|
||||||
str: "this is a test deadline exceeded: context deadline exceeded",
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(testcase.input.Error(), func(t *testing.T) {
|
|
||||||
t.Logf("input: %v", testcase.input)
|
|
||||||
gerr := ToGRPC(testcase.input)
|
|
||||||
t.Logf("grpc: %v", gerr)
|
|
||||||
ferr := FromGRPC(gerr)
|
|
||||||
t.Logf("recovered: %v", ferr)
|
|
||||||
|
|
||||||
if !errors.Is(ferr, testcase.cause) {
|
|
||||||
t.Fatalf("unexpected cause: !errors.Is(%v, %v)", ferr, testcase.cause)
|
|
||||||
}
|
|
||||||
|
|
||||||
expected := testcase.str
|
|
||||||
if expected == "" {
|
|
||||||
expected = testcase.cause.Error()
|
|
||||||
}
|
|
||||||
if ferr.Error() != expected {
|
|
||||||
t.Fatalf("unexpected string: %q != %q", ferr.Error(), expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user