update StatusDetails to handle Groups
This commit is contained in:
@@ -93,30 +93,32 @@ func FromObject(obj runtime.Object) error {
|
||||
}
|
||||
|
||||
// NewNotFound returns a new error which indicates that the resource of the kind and the name was not found.
|
||||
func NewNotFound(kind, name string) error {
|
||||
func NewNotFound(qualifiedResource unversioned.GroupResource, name string) error {
|
||||
return &StatusError{unversioned.Status{
|
||||
Status: unversioned.StatusFailure,
|
||||
Code: http.StatusNotFound,
|
||||
Reason: unversioned.StatusReasonNotFound,
|
||||
Details: &unversioned.StatusDetails{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Group: qualifiedResource.Group,
|
||||
Kind: qualifiedResource.Resource,
|
||||
Name: name,
|
||||
},
|
||||
Message: fmt.Sprintf("%s %q not found", kind, name),
|
||||
Message: fmt.Sprintf("%s %q not found", qualifiedResource.String(), name),
|
||||
}}
|
||||
}
|
||||
|
||||
// NewAlreadyExists returns an error indicating the item requested exists by that identifier.
|
||||
func NewAlreadyExists(kind, name string) error {
|
||||
func NewAlreadyExists(qualifiedResource unversioned.GroupResource, name string) error {
|
||||
return &StatusError{unversioned.Status{
|
||||
Status: unversioned.StatusFailure,
|
||||
Code: http.StatusConflict,
|
||||
Reason: unversioned.StatusReasonAlreadyExists,
|
||||
Details: &unversioned.StatusDetails{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Group: qualifiedResource.Group,
|
||||
Kind: qualifiedResource.Resource,
|
||||
Name: name,
|
||||
},
|
||||
Message: fmt.Sprintf("%s %q already exists", kind, name),
|
||||
Message: fmt.Sprintf("%s %q already exists", qualifiedResource.String(), name),
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -136,30 +138,32 @@ func NewUnauthorized(reason string) error {
|
||||
}
|
||||
|
||||
// NewForbidden returns an error indicating the requested action was forbidden
|
||||
func NewForbidden(kind, name string, err error) error {
|
||||
func NewForbidden(qualifiedResource unversioned.GroupResource, name string, err error) error {
|
||||
return &StatusError{unversioned.Status{
|
||||
Status: unversioned.StatusFailure,
|
||||
Code: http.StatusForbidden,
|
||||
Reason: unversioned.StatusReasonForbidden,
|
||||
Details: &unversioned.StatusDetails{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Group: qualifiedResource.Group,
|
||||
Kind: qualifiedResource.Resource,
|
||||
Name: name,
|
||||
},
|
||||
Message: fmt.Sprintf("%s %q is forbidden: %v", kind, name, err),
|
||||
Message: fmt.Sprintf("%s %q is forbidden: %v", qualifiedResource.String(), name, err),
|
||||
}}
|
||||
}
|
||||
|
||||
// NewConflict returns an error indicating the item can't be updated as provided.
|
||||
func NewConflict(kind, name string, err error) error {
|
||||
func NewConflict(qualifiedResource unversioned.GroupResource, name string, err error) error {
|
||||
return &StatusError{unversioned.Status{
|
||||
Status: unversioned.StatusFailure,
|
||||
Code: http.StatusConflict,
|
||||
Reason: unversioned.StatusReasonConflict,
|
||||
Details: &unversioned.StatusDetails{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Group: qualifiedResource.Group,
|
||||
Kind: qualifiedResource.Resource,
|
||||
Name: name,
|
||||
},
|
||||
Message: fmt.Sprintf("%s %q cannot be updated: %v", kind, name, err),
|
||||
Message: fmt.Sprintf("%s %q cannot be updated: %v", qualifiedResource.String(), name, err),
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -174,7 +178,7 @@ func NewGone(message string) error {
|
||||
}
|
||||
|
||||
// NewInvalid returns an error indicating the item is invalid and cannot be processed.
|
||||
func NewInvalid(kind, name string, errs field.ErrorList) error {
|
||||
func NewInvalid(qualifiedKind unversioned.GroupKind, name string, errs field.ErrorList) error {
|
||||
causes := make([]unversioned.StatusCause, 0, len(errs))
|
||||
for i := range errs {
|
||||
err := errs[i]
|
||||
@@ -189,11 +193,12 @@ func NewInvalid(kind, name string, errs field.ErrorList) error {
|
||||
Code: StatusUnprocessableEntity, // RFC 4918: StatusUnprocessableEntity
|
||||
Reason: unversioned.StatusReasonInvalid,
|
||||
Details: &unversioned.StatusDetails{
|
||||
Kind: kind,
|
||||
Group: qualifiedKind.Group,
|
||||
Kind: qualifiedKind.Kind,
|
||||
Name: name,
|
||||
Causes: causes,
|
||||
},
|
||||
Message: fmt.Sprintf("%s %q is invalid: %v", kind, name, errs.ToAggregate()),
|
||||
Message: fmt.Sprintf("%s %q is invalid: %v", qualifiedKind.String(), name, errs.ToAggregate()),
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -218,34 +223,42 @@ func NewServiceUnavailable(reason string) error {
|
||||
}
|
||||
|
||||
// NewMethodNotSupported returns an error indicating the requested action is not supported on this kind.
|
||||
func NewMethodNotSupported(kind, action string) error {
|
||||
func NewMethodNotSupported(qualifiedResource unversioned.GroupResource, action string) error {
|
||||
return &StatusError{unversioned.Status{
|
||||
Status: unversioned.StatusFailure,
|
||||
Code: http.StatusMethodNotAllowed,
|
||||
Reason: unversioned.StatusReasonMethodNotAllowed,
|
||||
Details: &unversioned.StatusDetails{
|
||||
Kind: kind,
|
||||
Group: qualifiedResource.Group,
|
||||
Kind: qualifiedResource.Resource,
|
||||
},
|
||||
Message: fmt.Sprintf("%s is not supported on resources of kind %q", action, kind),
|
||||
Message: fmt.Sprintf("%s is not supported on resources of kind %q", action, qualifiedResource.String()),
|
||||
}}
|
||||
}
|
||||
|
||||
// NewServerTimeout returns an error indicating the requested action could not be completed due to a
|
||||
// transient error, and the client should try again.
|
||||
func NewServerTimeout(kind, operation string, retryAfterSeconds int) error {
|
||||
func NewServerTimeout(qualifiedResource unversioned.GroupResource, operation string, retryAfterSeconds int) error {
|
||||
return &StatusError{unversioned.Status{
|
||||
Status: unversioned.StatusFailure,
|
||||
Code: http.StatusInternalServerError,
|
||||
Reason: unversioned.StatusReasonServerTimeout,
|
||||
Details: &unversioned.StatusDetails{
|
||||
Kind: kind,
|
||||
Group: qualifiedResource.Group,
|
||||
Kind: qualifiedResource.Resource,
|
||||
Name: operation,
|
||||
RetryAfterSeconds: int32(retryAfterSeconds),
|
||||
},
|
||||
Message: fmt.Sprintf("The %s operation against %s could not be completed at this time, please try again.", operation, kind),
|
||||
Message: fmt.Sprintf("The %s operation against %s could not be completed at this time, please try again.", operation, qualifiedResource.String()),
|
||||
}}
|
||||
}
|
||||
|
||||
// NewServerTimeoutForKind should not exist. Server timeouts happen when accessing resources, the Kind is just what we
|
||||
// happened to be looking at when the request failed. This delegates to keep code sane, but we should work towards removing this.
|
||||
func NewServerTimeoutForKind(qualifiedKind unversioned.GroupKind, operation string, retryAfterSeconds int) error {
|
||||
return NewServerTimeout(unversioned.GroupResource{Group: qualifiedKind.Group, Resource: qualifiedKind.Kind}, operation, retryAfterSeconds)
|
||||
}
|
||||
|
||||
// NewInternalError returns an error indicating the item is invalid and cannot be processed.
|
||||
func NewInternalError(err error) error {
|
||||
return &StatusError{unversioned.Status{
|
||||
@@ -274,7 +287,7 @@ func NewTimeoutError(message string, retryAfterSeconds int) error {
|
||||
}
|
||||
|
||||
// NewGenericServerResponse returns a new error for server responses that are not in a recognizable form.
|
||||
func NewGenericServerResponse(code int, verb, kind, name, serverMessage string, retryAfterSeconds int, isUnexpectedResponse bool) error {
|
||||
func NewGenericServerResponse(code int, verb string, qualifiedResource unversioned.GroupResource, name, serverMessage string, retryAfterSeconds int, isUnexpectedResponse bool) error {
|
||||
reason := unversioned.StatusReasonUnknown
|
||||
message := fmt.Sprintf("the server responded with the status code %d but did not return more information", code)
|
||||
switch code {
|
||||
@@ -316,10 +329,10 @@ func NewGenericServerResponse(code int, verb, kind, name, serverMessage string,
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case len(kind) > 0 && len(name) > 0:
|
||||
message = fmt.Sprintf("%s (%s %s %s)", message, strings.ToLower(verb), kind, name)
|
||||
case len(kind) > 0:
|
||||
message = fmt.Sprintf("%s (%s %s)", message, strings.ToLower(verb), kind)
|
||||
case !qualifiedResource.IsEmpty() && len(name) > 0:
|
||||
message = fmt.Sprintf("%s (%s %s %s)", message, strings.ToLower(verb), qualifiedResource.String(), name)
|
||||
case !qualifiedResource.IsEmpty():
|
||||
message = fmt.Sprintf("%s (%s %s)", message, strings.ToLower(verb), qualifiedResource.String())
|
||||
}
|
||||
var causes []unversioned.StatusCause
|
||||
if isUnexpectedResponse {
|
||||
@@ -337,8 +350,9 @@ func NewGenericServerResponse(code int, verb, kind, name, serverMessage string,
|
||||
Code: int32(code),
|
||||
Reason: reason,
|
||||
Details: &unversioned.StatusDetails{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Group: qualifiedResource.Group,
|
||||
Kind: qualifiedResource.Resource,
|
||||
Name: name,
|
||||
|
||||
Causes: causes,
|
||||
RetryAfterSeconds: int32(retryAfterSeconds),
|
||||
|
@@ -22,13 +22,14 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
func TestErrorNew(t *testing.T) {
|
||||
err := NewAlreadyExists("test", "1")
|
||||
err := NewAlreadyExists(api.Resource("tests"), "1")
|
||||
if !IsAlreadyExists(err) {
|
||||
t.Errorf("expected to be %s", unversioned.StatusReasonAlreadyExists)
|
||||
}
|
||||
@@ -54,34 +55,34 @@ func TestErrorNew(t *testing.T) {
|
||||
t.Errorf("expected to not be %s", unversioned.StatusReasonMethodNotAllowed)
|
||||
}
|
||||
|
||||
if !IsConflict(NewConflict("test", "2", errors.New("message"))) {
|
||||
if !IsConflict(NewConflict(api.Resource("tests"), "2", errors.New("message"))) {
|
||||
t.Errorf("expected to be conflict")
|
||||
}
|
||||
if !IsNotFound(NewNotFound("test", "3")) {
|
||||
if !IsNotFound(NewNotFound(api.Resource("tests"), "3")) {
|
||||
t.Errorf("expected to be %s", unversioned.StatusReasonNotFound)
|
||||
}
|
||||
if !IsInvalid(NewInvalid("test", "2", nil)) {
|
||||
if !IsInvalid(NewInvalid(api.Kind("Test"), "2", nil)) {
|
||||
t.Errorf("expected to be %s", unversioned.StatusReasonInvalid)
|
||||
}
|
||||
if !IsBadRequest(NewBadRequest("reason")) {
|
||||
t.Errorf("expected to be %s", unversioned.StatusReasonBadRequest)
|
||||
}
|
||||
if !IsForbidden(NewForbidden("test", "2", errors.New("reason"))) {
|
||||
if !IsForbidden(NewForbidden(api.Resource("tests"), "2", errors.New("reason"))) {
|
||||
t.Errorf("expected to be %s", unversioned.StatusReasonForbidden)
|
||||
}
|
||||
if !IsUnauthorized(NewUnauthorized("reason")) {
|
||||
t.Errorf("expected to be %s", unversioned.StatusReasonUnauthorized)
|
||||
}
|
||||
if !IsServerTimeout(NewServerTimeout("test", "reason", 0)) {
|
||||
if !IsServerTimeout(NewServerTimeout(api.Resource("tests"), "reason", 0)) {
|
||||
t.Errorf("expected to be %s", unversioned.StatusReasonServerTimeout)
|
||||
}
|
||||
if time, ok := SuggestsClientDelay(NewServerTimeout("test", "doing something", 10)); time != 10 || !ok {
|
||||
if time, ok := SuggestsClientDelay(NewServerTimeout(api.Resource("tests"), "doing something", 10)); time != 10 || !ok {
|
||||
t.Errorf("expected to be %s", unversioned.StatusReasonServerTimeout)
|
||||
}
|
||||
if time, ok := SuggestsClientDelay(NewTimeoutError("test reason", 10)); time != 10 || !ok {
|
||||
t.Errorf("expected to be %s", unversioned.StatusReasonTimeout)
|
||||
}
|
||||
if !IsMethodNotSupported(NewMethodNotSupported("foo", "delete")) {
|
||||
if !IsMethodNotSupported(NewMethodNotSupported(api.Resource("foos"), "delete")) {
|
||||
t.Errorf("expected to be %s", unversioned.StatusReasonMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
@@ -94,7 +95,7 @@ func TestNewInvalid(t *testing.T) {
|
||||
{
|
||||
field.Duplicate(field.NewPath("field[0].name"), "bar"),
|
||||
&unversioned.StatusDetails{
|
||||
Kind: "kind",
|
||||
Kind: "Kind",
|
||||
Name: "name",
|
||||
Causes: []unversioned.StatusCause{{
|
||||
Type: unversioned.CauseTypeFieldValueDuplicate,
|
||||
@@ -105,7 +106,7 @@ func TestNewInvalid(t *testing.T) {
|
||||
{
|
||||
field.Invalid(field.NewPath("field[0].name"), "bar", "detail"),
|
||||
&unversioned.StatusDetails{
|
||||
Kind: "kind",
|
||||
Kind: "Kind",
|
||||
Name: "name",
|
||||
Causes: []unversioned.StatusCause{{
|
||||
Type: unversioned.CauseTypeFieldValueInvalid,
|
||||
@@ -116,7 +117,7 @@ func TestNewInvalid(t *testing.T) {
|
||||
{
|
||||
field.NotFound(field.NewPath("field[0].name"), "bar"),
|
||||
&unversioned.StatusDetails{
|
||||
Kind: "kind",
|
||||
Kind: "Kind",
|
||||
Name: "name",
|
||||
Causes: []unversioned.StatusCause{{
|
||||
Type: unversioned.CauseTypeFieldValueNotFound,
|
||||
@@ -127,7 +128,7 @@ func TestNewInvalid(t *testing.T) {
|
||||
{
|
||||
field.NotSupported(field.NewPath("field[0].name"), "bar", nil),
|
||||
&unversioned.StatusDetails{
|
||||
Kind: "kind",
|
||||
Kind: "Kind",
|
||||
Name: "name",
|
||||
Causes: []unversioned.StatusCause{{
|
||||
Type: unversioned.CauseTypeFieldValueNotSupported,
|
||||
@@ -138,7 +139,7 @@ func TestNewInvalid(t *testing.T) {
|
||||
{
|
||||
field.Required(field.NewPath("field[0].name")),
|
||||
&unversioned.StatusDetails{
|
||||
Kind: "kind",
|
||||
Kind: "Kind",
|
||||
Name: "name",
|
||||
Causes: []unversioned.StatusCause{{
|
||||
Type: unversioned.CauseTypeFieldValueRequired,
|
||||
@@ -150,7 +151,7 @@ func TestNewInvalid(t *testing.T) {
|
||||
for i, testCase := range testCases {
|
||||
vErr, expected := testCase.Err, testCase.Details
|
||||
expected.Causes[0].Message = vErr.ErrorBody()
|
||||
err := NewInvalid("kind", "name", field.ErrorList{vErr})
|
||||
err := NewInvalid(api.Kind("Kind"), "name", field.ErrorList{vErr})
|
||||
status := err.(*StatusError).ErrStatus
|
||||
if status.Code != 422 || status.Reason != unversioned.StatusReasonInvalid {
|
||||
t.Errorf("%d: unexpected status: %#v", i, status)
|
||||
|
@@ -18,17 +18,18 @@ package etcd
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/storage"
|
||||
)
|
||||
|
||||
// InterpretListError converts a generic error on a retrieval
|
||||
// operation into the appropriate API error.
|
||||
func InterpretListError(err error, kind string) error {
|
||||
func InterpretListError(err error, qualifiedResource unversioned.GroupResource) error {
|
||||
switch {
|
||||
case storage.IsNotFound(err):
|
||||
return errors.NewNotFound(kind, "")
|
||||
return errors.NewNotFound(qualifiedResource, "")
|
||||
case storage.IsUnreachable(err):
|
||||
return errors.NewServerTimeout(kind, "list", 2) // TODO: make configurable or handled at a higher level
|
||||
return errors.NewServerTimeout(qualifiedResource, "list", 2) // TODO: make configurable or handled at a higher level
|
||||
default:
|
||||
return err
|
||||
}
|
||||
@@ -36,12 +37,12 @@ func InterpretListError(err error, kind string) error {
|
||||
|
||||
// InterpretGetError converts a generic error on a retrieval
|
||||
// operation into the appropriate API error.
|
||||
func InterpretGetError(err error, kind, name string) error {
|
||||
func InterpretGetError(err error, qualifiedResource unversioned.GroupResource, name string) error {
|
||||
switch {
|
||||
case storage.IsNotFound(err):
|
||||
return errors.NewNotFound(kind, name)
|
||||
return errors.NewNotFound(qualifiedResource, name)
|
||||
case storage.IsUnreachable(err):
|
||||
return errors.NewServerTimeout(kind, "get", 2) // TODO: make configurable or handled at a higher level
|
||||
return errors.NewServerTimeout(qualifiedResource, "get", 2) // TODO: make configurable or handled at a higher level
|
||||
default:
|
||||
return err
|
||||
}
|
||||
@@ -49,12 +50,12 @@ func InterpretGetError(err error, kind, name string) error {
|
||||
|
||||
// InterpretCreateError converts a generic error on a create
|
||||
// operation into the appropriate API error.
|
||||
func InterpretCreateError(err error, kind, name string) error {
|
||||
func InterpretCreateError(err error, qualifiedResource unversioned.GroupResource, name string) error {
|
||||
switch {
|
||||
case storage.IsNodeExist(err):
|
||||
return errors.NewAlreadyExists(kind, name)
|
||||
return errors.NewAlreadyExists(qualifiedResource, name)
|
||||
case storage.IsUnreachable(err):
|
||||
return errors.NewServerTimeout(kind, "create", 2) // TODO: make configurable or handled at a higher level
|
||||
return errors.NewServerTimeout(qualifiedResource, "create", 2) // TODO: make configurable or handled at a higher level
|
||||
default:
|
||||
return err
|
||||
}
|
||||
@@ -62,12 +63,12 @@ func InterpretCreateError(err error, kind, name string) error {
|
||||
|
||||
// InterpretUpdateError converts a generic error on a update
|
||||
// operation into the appropriate API error.
|
||||
func InterpretUpdateError(err error, kind, name string) error {
|
||||
func InterpretUpdateError(err error, qualifiedResource unversioned.GroupResource, name string) error {
|
||||
switch {
|
||||
case storage.IsTestFailed(err), storage.IsNodeExist(err):
|
||||
return errors.NewConflict(kind, name, err)
|
||||
return errors.NewConflict(qualifiedResource, name, err)
|
||||
case storage.IsUnreachable(err):
|
||||
return errors.NewServerTimeout(kind, "update", 2) // TODO: make configurable or handled at a higher level
|
||||
return errors.NewServerTimeout(qualifiedResource, "update", 2) // TODO: make configurable or handled at a higher level
|
||||
default:
|
||||
return err
|
||||
}
|
||||
@@ -75,12 +76,12 @@ func InterpretUpdateError(err error, kind, name string) error {
|
||||
|
||||
// InterpretDeleteError converts a generic error on a delete
|
||||
// operation into the appropriate API error.
|
||||
func InterpretDeleteError(err error, kind, name string) error {
|
||||
func InterpretDeleteError(err error, qualifiedResource unversioned.GroupResource, name string) error {
|
||||
switch {
|
||||
case storage.IsNotFound(err):
|
||||
return errors.NewNotFound(kind, name)
|
||||
return errors.NewNotFound(qualifiedResource, name)
|
||||
case storage.IsUnreachable(err):
|
||||
return errors.NewServerTimeout(kind, "delete", 2) // TODO: make configurable or handled at a higher level
|
||||
return errors.NewServerTimeout(qualifiedResource, "delete", 2) // TODO: make configurable or handled at a higher level
|
||||
default:
|
||||
return err
|
||||
}
|
||||
|
Reference in New Issue
Block a user