Storage: Consolidate error handling (#91167)
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
package resource
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// Package-level errors.
|
||||
var (
|
||||
ErrOptimisticLockingFailed = errors.New("optimistic locking failed")
|
||||
ErrUserNotFoundInContext = errors.New("user not found in context")
|
||||
ErrNotImplementedYet = errors.New("not implemented yet")
|
||||
)
|
||||
|
||||
func NewBadRequestError(msg string) *ErrorResult {
|
||||
return &ErrorResult{
|
||||
Message: msg,
|
||||
Code: http.StatusBadRequest,
|
||||
Reason: string(metav1.StatusReasonBadRequest),
|
||||
}
|
||||
}
|
||||
|
||||
func NewNotFoundError(key *ResourceKey) *ErrorResult {
|
||||
return &ErrorResult{
|
||||
Code: http.StatusNotFound,
|
||||
Details: &ErrorDetails{
|
||||
Group: key.Group,
|
||||
Kind: key.Resource, // yup, resource as kind same is true in apierrors.NewNotFound()
|
||||
Name: key.Name,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Convert golang errors to status result errors that can be returned to a client
|
||||
func AsErrorResult(err error) *ErrorResult {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
apistatus, ok := err.(apierrors.APIStatus)
|
||||
if ok {
|
||||
s := apistatus.Status()
|
||||
res := &ErrorResult{
|
||||
Message: s.Message,
|
||||
Reason: string(s.Reason),
|
||||
Code: s.Code,
|
||||
}
|
||||
if s.Details != nil {
|
||||
res.Details = &ErrorDetails{
|
||||
Group: s.Details.Group,
|
||||
Kind: s.Details.Kind,
|
||||
Name: s.Details.Name,
|
||||
Uid: string(s.Details.UID),
|
||||
RetryAfterSeconds: s.Details.RetryAfterSeconds,
|
||||
}
|
||||
for _, c := range s.Details.Causes {
|
||||
res.Details.Causes = append(res.Details.Causes, &ErrorCause{
|
||||
Reason: string(c.Type),
|
||||
Message: c.Message,
|
||||
Field: c.Field,
|
||||
})
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// TODO... better conversion??
|
||||
return &ErrorResult{
|
||||
Message: err.Error(),
|
||||
Code: 500,
|
||||
}
|
||||
}
|
||||
|
||||
func GetError(res *ErrorResult) error {
|
||||
if res == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
status := &apierrors.StatusError{ErrStatus: metav1.Status{
|
||||
Status: metav1.StatusFailure,
|
||||
Code: res.Code,
|
||||
Reason: metav1.StatusReason(res.Reason),
|
||||
Message: res.Message,
|
||||
}}
|
||||
if res.Details != nil {
|
||||
status.ErrStatus.Details = &metav1.StatusDetails{
|
||||
Group: res.Details.Group,
|
||||
Kind: res.Details.Kind,
|
||||
Name: res.Details.Name,
|
||||
UID: types.UID(res.Details.Uid),
|
||||
RetryAfterSeconds: res.Details.RetryAfterSeconds,
|
||||
}
|
||||
for _, c := range res.Details.Causes {
|
||||
status.ErrStatus.Details.Causes = append(status.ErrStatus.Details.Causes, metav1.StatusCause{
|
||||
Type: metav1.CauseType(c.Reason),
|
||||
Message: c.Message,
|
||||
Field: c.Field,
|
||||
})
|
||||
}
|
||||
}
|
||||
return status
|
||||
}
|
||||
Reference in New Issue
Block a user