mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 09:22:44 +00:00
update StatusDetails to handle Groups
This commit is contained in:
parent
5c4479f542
commit
9fda7f1812
@ -13070,6 +13070,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described)."
|
"description": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described)."
|
||||||
},
|
},
|
||||||
|
"group": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The group attribute of the resource associated with the status StatusReason."
|
||||||
|
},
|
||||||
"kind": {
|
"kind": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
|
"description": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
|
||||||
|
@ -2900,6 +2900,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described)."
|
"description": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described)."
|
||||||
},
|
},
|
||||||
|
"group": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The group attribute of the resource associated with the status StatusReason."
|
||||||
|
},
|
||||||
"kind": {
|
"kind": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
|
"description": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
|
||||||
|
@ -1331,6 +1331,13 @@ Both these may change in the future. Incoming requests are matched against the h
|
|||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">group</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The group attribute of the resource associated with the status StatusReason.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">kind</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">kind</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
@ -4278,7 +4285,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
Last updated 2015-12-14 19:06:25 UTC
|
Last updated 2015-12-16 14:33:53 UTC
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -4435,6 +4435,13 @@ The resulting set of endpoints can be viewed as:<br>
|
|||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">group</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The group attribute of the resource associated with the status StatusReason.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">kind</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">kind</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
@ -6918,7 +6925,7 @@ The resulting set of endpoints can be viewed as:<br>
|
|||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
Last updated 2015-12-16 19:00:42 UTC
|
Last updated 2015-12-17 12:59:31 UTC
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -23,14 +23,14 @@ import (
|
|||||||
utilerrors "k8s.io/kubernetes/pkg/util/errors"
|
utilerrors "k8s.io/kubernetes/pkg/util/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func extractKindName(a Attributes) (name string, kind unversioned.GroupKind, err error) {
|
func extractResourceName(a Attributes) (name string, resource unversioned.GroupResource, err error) {
|
||||||
name = "Unknown"
|
name = "Unknown"
|
||||||
kind = a.GetKind()
|
resource = a.GetResource()
|
||||||
obj := a.GetObject()
|
obj := a.GetObject()
|
||||||
if obj != nil {
|
if obj != nil {
|
||||||
objectMeta, err := api.ObjectMetaFor(obj)
|
objectMeta, err := api.ObjectMetaFor(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", unversioned.GroupKind{}, err
|
return "", unversioned.GroupResource{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is necessary because name object name generation has not occurred yet
|
// this is necessary because name object name generation has not occurred yet
|
||||||
@ -40,7 +40,7 @@ func extractKindName(a Attributes) (name string, kind unversioned.GroupKind, err
|
|||||||
name = objectMeta.GenerateName
|
name = objectMeta.GenerateName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return name, kind, nil
|
return name, resource, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewForbidden is a utility function to return a well-formatted admission control error response
|
// NewForbidden is a utility function to return a well-formatted admission control error response
|
||||||
@ -49,18 +49,18 @@ func NewForbidden(a Attributes, internalError error) error {
|
|||||||
if apierrors.IsForbidden(internalError) {
|
if apierrors.IsForbidden(internalError) {
|
||||||
return internalError
|
return internalError
|
||||||
}
|
}
|
||||||
name, kind, err := extractKindName(a)
|
name, resource, err := extractResourceName(a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apierrors.NewInternalError(utilerrors.NewAggregate([]error{internalError, err}))
|
return apierrors.NewInternalError(utilerrors.NewAggregate([]error{internalError, err}))
|
||||||
}
|
}
|
||||||
return apierrors.NewForbidden(kind.Kind, name, internalError)
|
return apierrors.NewForbidden(resource, name, internalError)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNotFound is a utility function to return a well-formatted admission control error response
|
// NewNotFound is a utility function to return a well-formatted admission control error response
|
||||||
func NewNotFound(a Attributes) error {
|
func NewNotFound(a Attributes) error {
|
||||||
name, kind, err := extractKindName(a)
|
name, resource, err := extractResourceName(a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apierrors.NewInternalError(err)
|
return apierrors.NewInternalError(err)
|
||||||
}
|
}
|
||||||
return apierrors.NewNotFound(kind.Kind, name)
|
return apierrors.NewNotFound(resource, name)
|
||||||
}
|
}
|
||||||
|
@ -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.
|
// 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{
|
return &StatusError{unversioned.Status{
|
||||||
Status: unversioned.StatusFailure,
|
Status: unversioned.StatusFailure,
|
||||||
Code: http.StatusNotFound,
|
Code: http.StatusNotFound,
|
||||||
Reason: unversioned.StatusReasonNotFound,
|
Reason: unversioned.StatusReasonNotFound,
|
||||||
Details: &unversioned.StatusDetails{
|
Details: &unversioned.StatusDetails{
|
||||||
Kind: kind,
|
Group: qualifiedResource.Group,
|
||||||
Name: name,
|
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.
|
// 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{
|
return &StatusError{unversioned.Status{
|
||||||
Status: unversioned.StatusFailure,
|
Status: unversioned.StatusFailure,
|
||||||
Code: http.StatusConflict,
|
Code: http.StatusConflict,
|
||||||
Reason: unversioned.StatusReasonAlreadyExists,
|
Reason: unversioned.StatusReasonAlreadyExists,
|
||||||
Details: &unversioned.StatusDetails{
|
Details: &unversioned.StatusDetails{
|
||||||
Kind: kind,
|
Group: qualifiedResource.Group,
|
||||||
Name: name,
|
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
|
// 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{
|
return &StatusError{unversioned.Status{
|
||||||
Status: unversioned.StatusFailure,
|
Status: unversioned.StatusFailure,
|
||||||
Code: http.StatusForbidden,
|
Code: http.StatusForbidden,
|
||||||
Reason: unversioned.StatusReasonForbidden,
|
Reason: unversioned.StatusReasonForbidden,
|
||||||
Details: &unversioned.StatusDetails{
|
Details: &unversioned.StatusDetails{
|
||||||
Kind: kind,
|
Group: qualifiedResource.Group,
|
||||||
Name: name,
|
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.
|
// 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{
|
return &StatusError{unversioned.Status{
|
||||||
Status: unversioned.StatusFailure,
|
Status: unversioned.StatusFailure,
|
||||||
Code: http.StatusConflict,
|
Code: http.StatusConflict,
|
||||||
Reason: unversioned.StatusReasonConflict,
|
Reason: unversioned.StatusReasonConflict,
|
||||||
Details: &unversioned.StatusDetails{
|
Details: &unversioned.StatusDetails{
|
||||||
Kind: kind,
|
Group: qualifiedResource.Group,
|
||||||
Name: name,
|
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.
|
// 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))
|
causes := make([]unversioned.StatusCause, 0, len(errs))
|
||||||
for i := range errs {
|
for i := range errs {
|
||||||
err := errs[i]
|
err := errs[i]
|
||||||
@ -189,11 +193,12 @@ func NewInvalid(kind, name string, errs field.ErrorList) error {
|
|||||||
Code: StatusUnprocessableEntity, // RFC 4918: StatusUnprocessableEntity
|
Code: StatusUnprocessableEntity, // RFC 4918: StatusUnprocessableEntity
|
||||||
Reason: unversioned.StatusReasonInvalid,
|
Reason: unversioned.StatusReasonInvalid,
|
||||||
Details: &unversioned.StatusDetails{
|
Details: &unversioned.StatusDetails{
|
||||||
Kind: kind,
|
Group: qualifiedKind.Group,
|
||||||
|
Kind: qualifiedKind.Kind,
|
||||||
Name: name,
|
Name: name,
|
||||||
Causes: causes,
|
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.
|
// 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{
|
return &StatusError{unversioned.Status{
|
||||||
Status: unversioned.StatusFailure,
|
Status: unversioned.StatusFailure,
|
||||||
Code: http.StatusMethodNotAllowed,
|
Code: http.StatusMethodNotAllowed,
|
||||||
Reason: unversioned.StatusReasonMethodNotAllowed,
|
Reason: unversioned.StatusReasonMethodNotAllowed,
|
||||||
Details: &unversioned.StatusDetails{
|
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
|
// NewServerTimeout returns an error indicating the requested action could not be completed due to a
|
||||||
// transient error, and the client should try again.
|
// 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{
|
return &StatusError{unversioned.Status{
|
||||||
Status: unversioned.StatusFailure,
|
Status: unversioned.StatusFailure,
|
||||||
Code: http.StatusInternalServerError,
|
Code: http.StatusInternalServerError,
|
||||||
Reason: unversioned.StatusReasonServerTimeout,
|
Reason: unversioned.StatusReasonServerTimeout,
|
||||||
Details: &unversioned.StatusDetails{
|
Details: &unversioned.StatusDetails{
|
||||||
Kind: kind,
|
Group: qualifiedResource.Group,
|
||||||
|
Kind: qualifiedResource.Resource,
|
||||||
Name: operation,
|
Name: operation,
|
||||||
RetryAfterSeconds: int32(retryAfterSeconds),
|
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.
|
// NewInternalError returns an error indicating the item is invalid and cannot be processed.
|
||||||
func NewInternalError(err error) error {
|
func NewInternalError(err error) error {
|
||||||
return &StatusError{unversioned.Status{
|
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.
|
// 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
|
reason := unversioned.StatusReasonUnknown
|
||||||
message := fmt.Sprintf("the server responded with the status code %d but did not return more information", code)
|
message := fmt.Sprintf("the server responded with the status code %d but did not return more information", code)
|
||||||
switch code {
|
switch code {
|
||||||
@ -316,10 +329,10 @@ func NewGenericServerResponse(code int, verb, kind, name, serverMessage string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case len(kind) > 0 && len(name) > 0:
|
case !qualifiedResource.IsEmpty() && len(name) > 0:
|
||||||
message = fmt.Sprintf("%s (%s %s %s)", message, strings.ToLower(verb), kind, name)
|
message = fmt.Sprintf("%s (%s %s %s)", message, strings.ToLower(verb), qualifiedResource.String(), name)
|
||||||
case len(kind) > 0:
|
case !qualifiedResource.IsEmpty():
|
||||||
message = fmt.Sprintf("%s (%s %s)", message, strings.ToLower(verb), kind)
|
message = fmt.Sprintf("%s (%s %s)", message, strings.ToLower(verb), qualifiedResource.String())
|
||||||
}
|
}
|
||||||
var causes []unversioned.StatusCause
|
var causes []unversioned.StatusCause
|
||||||
if isUnexpectedResponse {
|
if isUnexpectedResponse {
|
||||||
@ -337,8 +350,9 @@ func NewGenericServerResponse(code int, verb, kind, name, serverMessage string,
|
|||||||
Code: int32(code),
|
Code: int32(code),
|
||||||
Reason: reason,
|
Reason: reason,
|
||||||
Details: &unversioned.StatusDetails{
|
Details: &unversioned.StatusDetails{
|
||||||
Kind: kind,
|
Group: qualifiedResource.Group,
|
||||||
Name: name,
|
Kind: qualifiedResource.Resource,
|
||||||
|
Name: name,
|
||||||
|
|
||||||
Causes: causes,
|
Causes: causes,
|
||||||
RetryAfterSeconds: int32(retryAfterSeconds),
|
RetryAfterSeconds: int32(retryAfterSeconds),
|
||||||
|
@ -22,13 +22,14 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestErrorNew(t *testing.T) {
|
func TestErrorNew(t *testing.T) {
|
||||||
err := NewAlreadyExists("test", "1")
|
err := NewAlreadyExists(api.Resource("tests"), "1")
|
||||||
if !IsAlreadyExists(err) {
|
if !IsAlreadyExists(err) {
|
||||||
t.Errorf("expected to be %s", unversioned.StatusReasonAlreadyExists)
|
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)
|
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")
|
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)
|
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)
|
t.Errorf("expected to be %s", unversioned.StatusReasonInvalid)
|
||||||
}
|
}
|
||||||
if !IsBadRequest(NewBadRequest("reason")) {
|
if !IsBadRequest(NewBadRequest("reason")) {
|
||||||
t.Errorf("expected to be %s", unversioned.StatusReasonBadRequest)
|
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)
|
t.Errorf("expected to be %s", unversioned.StatusReasonForbidden)
|
||||||
}
|
}
|
||||||
if !IsUnauthorized(NewUnauthorized("reason")) {
|
if !IsUnauthorized(NewUnauthorized("reason")) {
|
||||||
t.Errorf("expected to be %s", unversioned.StatusReasonUnauthorized)
|
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)
|
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)
|
t.Errorf("expected to be %s", unversioned.StatusReasonServerTimeout)
|
||||||
}
|
}
|
||||||
if time, ok := SuggestsClientDelay(NewTimeoutError("test reason", 10)); time != 10 || !ok {
|
if time, ok := SuggestsClientDelay(NewTimeoutError("test reason", 10)); time != 10 || !ok {
|
||||||
t.Errorf("expected to be %s", unversioned.StatusReasonTimeout)
|
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)
|
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"),
|
field.Duplicate(field.NewPath("field[0].name"), "bar"),
|
||||||
&unversioned.StatusDetails{
|
&unversioned.StatusDetails{
|
||||||
Kind: "kind",
|
Kind: "Kind",
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Causes: []unversioned.StatusCause{{
|
Causes: []unversioned.StatusCause{{
|
||||||
Type: unversioned.CauseTypeFieldValueDuplicate,
|
Type: unversioned.CauseTypeFieldValueDuplicate,
|
||||||
@ -105,7 +106,7 @@ func TestNewInvalid(t *testing.T) {
|
|||||||
{
|
{
|
||||||
field.Invalid(field.NewPath("field[0].name"), "bar", "detail"),
|
field.Invalid(field.NewPath("field[0].name"), "bar", "detail"),
|
||||||
&unversioned.StatusDetails{
|
&unversioned.StatusDetails{
|
||||||
Kind: "kind",
|
Kind: "Kind",
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Causes: []unversioned.StatusCause{{
|
Causes: []unversioned.StatusCause{{
|
||||||
Type: unversioned.CauseTypeFieldValueInvalid,
|
Type: unversioned.CauseTypeFieldValueInvalid,
|
||||||
@ -116,7 +117,7 @@ func TestNewInvalid(t *testing.T) {
|
|||||||
{
|
{
|
||||||
field.NotFound(field.NewPath("field[0].name"), "bar"),
|
field.NotFound(field.NewPath("field[0].name"), "bar"),
|
||||||
&unversioned.StatusDetails{
|
&unversioned.StatusDetails{
|
||||||
Kind: "kind",
|
Kind: "Kind",
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Causes: []unversioned.StatusCause{{
|
Causes: []unversioned.StatusCause{{
|
||||||
Type: unversioned.CauseTypeFieldValueNotFound,
|
Type: unversioned.CauseTypeFieldValueNotFound,
|
||||||
@ -127,7 +128,7 @@ func TestNewInvalid(t *testing.T) {
|
|||||||
{
|
{
|
||||||
field.NotSupported(field.NewPath("field[0].name"), "bar", nil),
|
field.NotSupported(field.NewPath("field[0].name"), "bar", nil),
|
||||||
&unversioned.StatusDetails{
|
&unversioned.StatusDetails{
|
||||||
Kind: "kind",
|
Kind: "Kind",
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Causes: []unversioned.StatusCause{{
|
Causes: []unversioned.StatusCause{{
|
||||||
Type: unversioned.CauseTypeFieldValueNotSupported,
|
Type: unversioned.CauseTypeFieldValueNotSupported,
|
||||||
@ -138,7 +139,7 @@ func TestNewInvalid(t *testing.T) {
|
|||||||
{
|
{
|
||||||
field.Required(field.NewPath("field[0].name")),
|
field.Required(field.NewPath("field[0].name")),
|
||||||
&unversioned.StatusDetails{
|
&unversioned.StatusDetails{
|
||||||
Kind: "kind",
|
Kind: "Kind",
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Causes: []unversioned.StatusCause{{
|
Causes: []unversioned.StatusCause{{
|
||||||
Type: unversioned.CauseTypeFieldValueRequired,
|
Type: unversioned.CauseTypeFieldValueRequired,
|
||||||
@ -150,7 +151,7 @@ func TestNewInvalid(t *testing.T) {
|
|||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
vErr, expected := testCase.Err, testCase.Details
|
vErr, expected := testCase.Err, testCase.Details
|
||||||
expected.Causes[0].Message = vErr.ErrorBody()
|
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
|
status := err.(*StatusError).ErrStatus
|
||||||
if status.Code != 422 || status.Reason != unversioned.StatusReasonInvalid {
|
if status.Code != 422 || status.Reason != unversioned.StatusReasonInvalid {
|
||||||
t.Errorf("%d: unexpected status: %#v", i, status)
|
t.Errorf("%d: unexpected status: %#v", i, status)
|
||||||
|
@ -18,17 +18,18 @@ package etcd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/storage"
|
"k8s.io/kubernetes/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InterpretListError converts a generic error on a retrieval
|
// InterpretListError converts a generic error on a retrieval
|
||||||
// operation into the appropriate API error.
|
// operation into the appropriate API error.
|
||||||
func InterpretListError(err error, kind string) error {
|
func InterpretListError(err error, qualifiedResource unversioned.GroupResource) error {
|
||||||
switch {
|
switch {
|
||||||
case storage.IsNotFound(err):
|
case storage.IsNotFound(err):
|
||||||
return errors.NewNotFound(kind, "")
|
return errors.NewNotFound(qualifiedResource, "")
|
||||||
case storage.IsUnreachable(err):
|
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:
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -36,12 +37,12 @@ func InterpretListError(err error, kind string) error {
|
|||||||
|
|
||||||
// InterpretGetError converts a generic error on a retrieval
|
// InterpretGetError converts a generic error on a retrieval
|
||||||
// operation into the appropriate API error.
|
// 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 {
|
switch {
|
||||||
case storage.IsNotFound(err):
|
case storage.IsNotFound(err):
|
||||||
return errors.NewNotFound(kind, name)
|
return errors.NewNotFound(qualifiedResource, name)
|
||||||
case storage.IsUnreachable(err):
|
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:
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -49,12 +50,12 @@ func InterpretGetError(err error, kind, name string) error {
|
|||||||
|
|
||||||
// InterpretCreateError converts a generic error on a create
|
// InterpretCreateError converts a generic error on a create
|
||||||
// operation into the appropriate API error.
|
// 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 {
|
switch {
|
||||||
case storage.IsNodeExist(err):
|
case storage.IsNodeExist(err):
|
||||||
return errors.NewAlreadyExists(kind, name)
|
return errors.NewAlreadyExists(qualifiedResource, name)
|
||||||
case storage.IsUnreachable(err):
|
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:
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -62,12 +63,12 @@ func InterpretCreateError(err error, kind, name string) error {
|
|||||||
|
|
||||||
// InterpretUpdateError converts a generic error on a update
|
// InterpretUpdateError converts a generic error on a update
|
||||||
// operation into the appropriate API error.
|
// 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 {
|
switch {
|
||||||
case storage.IsTestFailed(err), storage.IsNodeExist(err):
|
case storage.IsTestFailed(err), storage.IsNodeExist(err):
|
||||||
return errors.NewConflict(kind, name, err)
|
return errors.NewConflict(qualifiedResource, name, err)
|
||||||
case storage.IsUnreachable(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:
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -75,12 +76,12 @@ func InterpretUpdateError(err error, kind, name string) error {
|
|||||||
|
|
||||||
// InterpretDeleteError converts a generic error on a delete
|
// InterpretDeleteError converts a generic error on a delete
|
||||||
// operation into the appropriate API error.
|
// 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 {
|
switch {
|
||||||
case storage.IsNotFound(err):
|
case storage.IsNotFound(err):
|
||||||
return errors.NewNotFound(kind, name)
|
return errors.NewNotFound(qualifiedResource, name)
|
||||||
case storage.IsUnreachable(err):
|
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:
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package rest
|
|||||||
import (
|
import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/api/validation"
|
"k8s.io/kubernetes/pkg/api/validation"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||||
@ -71,14 +72,14 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx api.Context, obj runtime.Obje
|
|||||||
api.GenerateName(strategy, objectMeta)
|
api.GenerateName(strategy, objectMeta)
|
||||||
|
|
||||||
if errs := strategy.Validate(ctx, obj); len(errs) > 0 {
|
if errs := strategy.Validate(ctx, obj); len(errs) > 0 {
|
||||||
return errors.NewInvalid(kind, objectMeta.Name, errs)
|
return errors.NewInvalid(kind.GroupKind(), objectMeta.Name, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom validation (including name validation) passed
|
// Custom validation (including name validation) passed
|
||||||
// Now run common validation on object meta
|
// Now run common validation on object meta
|
||||||
// Do this *after* custom validation so that specific error messages are shown whenever possible
|
// Do this *after* custom validation so that specific error messages are shown whenever possible
|
||||||
if errs := validation.ValidateObjectMeta(objectMeta, strategy.NamespaceScoped(), validation.ValidatePathSegmentName, field.NewPath("metadata")); len(errs) > 0 {
|
if errs := validation.ValidateObjectMeta(objectMeta, strategy.NamespaceScoped(), validation.ValidatePathSegmentName, field.NewPath("metadata")); len(errs) > 0 {
|
||||||
return errors.NewInvalid(kind, objectMeta.Name, errs)
|
return errors.NewInvalid(kind.GroupKind(), objectMeta.Name, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
strategy.Canonicalize(obj)
|
strategy.Canonicalize(obj)
|
||||||
@ -102,18 +103,18 @@ func CheckGeneratedNameError(strategy RESTCreateStrategy, err error, obj runtime
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.NewServerTimeout(kind, "POST", 0)
|
return errors.NewServerTimeoutForKind(kind.GroupKind(), "POST", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error.
|
// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error.
|
||||||
func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (*api.ObjectMeta, string, error) {
|
func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (*api.ObjectMeta, unversioned.GroupVersionKind, error) {
|
||||||
objectMeta, err := api.ObjectMetaFor(obj)
|
objectMeta, err := api.ObjectMetaFor(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", errors.NewInternalError(err)
|
return nil, unversioned.GroupVersionKind{}, errors.NewInternalError(err)
|
||||||
}
|
}
|
||||||
gvk, err := typer.ObjectKind(obj)
|
kind, err := typer.ObjectKind(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", errors.NewInternalError(err)
|
return nil, unversioned.GroupVersionKind{}, errors.NewInternalError(err)
|
||||||
}
|
}
|
||||||
return objectMeta, gvk.Kind, nil
|
return objectMeta, kind, nil
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx api.Context, obj, old runtime
|
|||||||
|
|
||||||
errs = append(errs, strategy.ValidateUpdate(ctx, obj, old)...)
|
errs = append(errs, strategy.ValidateUpdate(ctx, obj, old)...)
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
return errors.NewInvalid(kind, objectMeta.Name, errs)
|
return errors.NewInvalid(kind.GroupKind(), objectMeta.Name, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
strategy.Canonicalize(obj)
|
strategy.Canonicalize(obj)
|
||||||
|
@ -33,8 +33,15 @@ func (gr GroupResource) WithVersion(version string) GroupVersionResource {
|
|||||||
return GroupVersionResource{Group: gr.Group, Version: version, Resource: gr.Resource}
|
return GroupVersionResource{Group: gr.Group, Version: version, Resource: gr.Resource}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gr GroupResource) IsEmpty() bool {
|
||||||
|
return len(gr.Group) == 0 && len(gr.Resource) == 0
|
||||||
|
}
|
||||||
|
|
||||||
func (gr *GroupResource) String() string {
|
func (gr *GroupResource) String() string {
|
||||||
return strings.Join([]string{gr.Group, ", Resource=", gr.Resource}, "")
|
if len(gr.Group) == 0 {
|
||||||
|
return gr.Resource
|
||||||
|
}
|
||||||
|
return gr.Resource + "." + gr.Group
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion
|
// GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion
|
||||||
@ -66,12 +73,19 @@ type GroupKind struct {
|
|||||||
Kind string
|
Kind string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gk GroupKind) IsEmpty() bool {
|
||||||
|
return len(gk.Group) == 0 && len(gk.Kind) == 0
|
||||||
|
}
|
||||||
|
|
||||||
func (gk GroupKind) WithVersion(version string) GroupVersionKind {
|
func (gk GroupKind) WithVersion(version string) GroupVersionKind {
|
||||||
return GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind}
|
return GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gk *GroupKind) String() string {
|
func (gk *GroupKind) String() string {
|
||||||
return gk.Group + ", Kind=" + gk.Kind
|
if len(gk.Group) == 0 {
|
||||||
|
return gk.Kind
|
||||||
|
}
|
||||||
|
return gk.Kind + "." + gk.Group
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupVersionKind unambiguously identifies a kind. It doesn't anonymously include GroupVersion
|
// GroupVersionKind unambiguously identifies a kind. It doesn't anonymously include GroupVersion
|
||||||
|
@ -121,6 +121,8 @@ type StatusDetails struct {
|
|||||||
// The name attribute of the resource associated with the status StatusReason
|
// The name attribute of the resource associated with the status StatusReason
|
||||||
// (when there is a single name which can be described).
|
// (when there is a single name which can be described).
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
// The group attribute of the resource associated with the status StatusReason.
|
||||||
|
Group string `json:"group,omitempty"`
|
||||||
// The kind attribute of the resource associated with the status StatusReason.
|
// The kind attribute of the resource associated with the status StatusReason.
|
||||||
// On some operations may differ from the requested resource Kind.
|
// On some operations may differ from the requested resource Kind.
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
|
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
|
||||||
|
@ -164,6 +164,7 @@ func (StatusCause) SwaggerDoc() map[string]string {
|
|||||||
var map_StatusDetails = map[string]string{
|
var map_StatusDetails = map[string]string{
|
||||||
"": "StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.",
|
"": "StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.",
|
||||||
"name": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described).",
|
"name": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described).",
|
||||||
|
"group": "The group attribute of the resource associated with the status StatusReason.",
|
||||||
"kind": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds",
|
"kind": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds",
|
||||||
"causes": "The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes.",
|
"causes": "The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes.",
|
||||||
"retryAfterSeconds": "If specified, the time in seconds before the operation should be retried.",
|
"retryAfterSeconds": "If specified, the time in seconds before the operation should be retried.",
|
||||||
|
@ -211,7 +211,7 @@ func logStackOnRecover(panicReason interface{}, httpWriter http.ResponseWriter)
|
|||||||
glog.Errorln(buffer.String())
|
glog.Errorln(buffer.String())
|
||||||
|
|
||||||
// TODO: make status unversioned or plumb enough of the request to deduce the requested API version
|
// TODO: make status unversioned or plumb enough of the request to deduce the requested API version
|
||||||
errorJSON(apierrors.NewGenericServerResponse(http.StatusInternalServerError, "", "", "", "", 0, false), latest.GroupOrDie(api.GroupName).Codec, httpWriter)
|
errorJSON(apierrors.NewGenericServerResponse(http.StatusInternalServerError, "", api.Resource(""), "", "", 0, false), latest.GroupOrDie(api.GroupName).Codec, httpWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func InstallServiceErrorHandler(container *restful.Container, requestResolver *RequestInfoResolver, apiVersions []string) {
|
func InstallServiceErrorHandler(container *restful.Container, requestResolver *RequestInfoResolver, apiVersions []string) {
|
||||||
@ -234,7 +234,7 @@ func serviceErrorHandler(requestResolver *RequestInfoResolver, apiVersions []str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
errorJSON(apierrors.NewGenericServerResponse(serviceErr.Code, "", "", "", "", 0, false), codec, response.ResponseWriter)
|
errorJSON(apierrors.NewGenericServerResponse(serviceErr.Code, "", api.Resource(""), "", "", 0, false), codec, response.ResponseWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a service to return the supported api versions at the legacy /api.
|
// Adds a service to return the supported api versions at the legacy /api.
|
||||||
|
@ -1489,7 +1489,7 @@ func TestGetNamespaceSelfLink(t *testing.T) {
|
|||||||
func TestGetMissing(t *testing.T) {
|
func TestGetMissing(t *testing.T) {
|
||||||
storage := map[string]rest.Storage{}
|
storage := map[string]rest.Storage{}
|
||||||
simpleStorage := SimpleRESTStorage{
|
simpleStorage := SimpleRESTStorage{
|
||||||
errors: map[string]error{"get": apierrs.NewNotFound("simple", "id")},
|
errors: map[string]error{"get": apierrs.NewNotFound(api.Resource("simples"), "id")},
|
||||||
}
|
}
|
||||||
storage["simple"] = &simpleStorage
|
storage["simple"] = &simpleStorage
|
||||||
handler := handle(storage)
|
handler := handle(storage)
|
||||||
@ -1590,7 +1590,7 @@ func TestConnectResponderError(t *testing.T) {
|
|||||||
connectStorage := &ConnecterRESTStorage{}
|
connectStorage := &ConnecterRESTStorage{}
|
||||||
connectStorage.handlerFunc = func() http.Handler {
|
connectStorage.handlerFunc = func() http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
connectStorage.receivedResponder.Error(apierrs.NewForbidden("simple", itemID, errors.New("you are terminated")))
|
connectStorage.receivedResponder.Error(apierrs.NewForbidden(api.Resource("simples"), itemID, errors.New("you are terminated")))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
storage := map[string]rest.Storage{
|
storage := map[string]rest.Storage{
|
||||||
@ -1897,7 +1897,7 @@ func TestDeleteMissing(t *testing.T) {
|
|||||||
storage := map[string]rest.Storage{}
|
storage := map[string]rest.Storage{}
|
||||||
ID := "id"
|
ID := "id"
|
||||||
simpleStorage := SimpleRESTStorage{
|
simpleStorage := SimpleRESTStorage{
|
||||||
errors: map[string]error{"delete": apierrs.NewNotFound("simple", ID)},
|
errors: map[string]error{"delete": apierrs.NewNotFound(api.Resource("simples"), ID)},
|
||||||
}
|
}
|
||||||
storage["simple"] = &simpleStorage
|
storage["simple"] = &simpleStorage
|
||||||
handler := handle(storage)
|
handler := handle(storage)
|
||||||
@ -2198,7 +2198,7 @@ func TestUpdateMissing(t *testing.T) {
|
|||||||
storage := map[string]rest.Storage{}
|
storage := map[string]rest.Storage{}
|
||||||
ID := "id"
|
ID := "id"
|
||||||
simpleStorage := SimpleRESTStorage{
|
simpleStorage := SimpleRESTStorage{
|
||||||
errors: map[string]error{"update": apierrs.NewNotFound("simple", ID)},
|
errors: map[string]error{"update": apierrs.NewNotFound(api.Resource("simples"), ID)},
|
||||||
}
|
}
|
||||||
storage["simple"] = &simpleStorage
|
storage["simple"] = &simpleStorage
|
||||||
handler := handle(storage)
|
handler := handle(storage)
|
||||||
@ -2233,7 +2233,7 @@ func TestCreateNotFound(t *testing.T) {
|
|||||||
"simple": &SimpleRESTStorage{
|
"simple": &SimpleRESTStorage{
|
||||||
// storage.Create can fail with not found error in theory.
|
// storage.Create can fail with not found error in theory.
|
||||||
// See http://pr.k8s.io/486#discussion_r15037092.
|
// See http://pr.k8s.io/486#discussion_r15037092.
|
||||||
errors: map[string]error{"create": apierrs.NewNotFound("simple", "id")},
|
errors: map[string]error{"create": apierrs.NewNotFound(api.Resource("simples"), "id")},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
server := httptest.NewServer(handler)
|
server := httptest.NewServer(handler)
|
||||||
@ -2729,7 +2729,7 @@ func expectApiStatus(t *testing.T, method, url string, data []byte, code int) *u
|
|||||||
func TestDelayReturnsError(t *testing.T) {
|
func TestDelayReturnsError(t *testing.T) {
|
||||||
storage := SimpleRESTStorage{
|
storage := SimpleRESTStorage{
|
||||||
injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
|
injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
|
||||||
return nil, apierrs.NewAlreadyExists("foo", "bar")
|
return nil, apierrs.NewAlreadyExists(api.Resource("foos"), "bar")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
handler := handle(map[string]rest.Storage{"foo": &storage})
|
handler := handle(map[string]rest.Storage{"foo": &storage})
|
||||||
|
@ -22,40 +22,44 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestErrorsToAPIStatus(t *testing.T) {
|
func TestErrorsToAPIStatus(t *testing.T) {
|
||||||
cases := map[error]unversioned.Status{
|
cases := map[error]unversioned.Status{
|
||||||
errors.NewNotFound("foo", "bar"): {
|
errors.NewNotFound(unversioned.GroupResource{Group: "legacy.kubernetes.io", Resource: "foos"}, "bar"): {
|
||||||
Status: unversioned.StatusFailure,
|
Status: unversioned.StatusFailure,
|
||||||
Code: http.StatusNotFound,
|
Code: http.StatusNotFound,
|
||||||
Reason: unversioned.StatusReasonNotFound,
|
Reason: unversioned.StatusReasonNotFound,
|
||||||
Message: "foo \"bar\" not found",
|
Message: "foos.legacy.kubernetes.io \"bar\" not found",
|
||||||
Details: &unversioned.StatusDetails{
|
Details: &unversioned.StatusDetails{
|
||||||
Kind: "foo",
|
Group: "legacy.kubernetes.io",
|
||||||
Name: "bar",
|
Kind: "foos",
|
||||||
|
Name: "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
errors.NewAlreadyExists("foo", "bar"): {
|
errors.NewAlreadyExists(api.Resource("foos"), "bar"): {
|
||||||
Status: unversioned.StatusFailure,
|
Status: unversioned.StatusFailure,
|
||||||
Code: http.StatusConflict,
|
Code: http.StatusConflict,
|
||||||
Reason: "AlreadyExists",
|
Reason: "AlreadyExists",
|
||||||
Message: "foo \"bar\" already exists",
|
Message: "foos \"bar\" already exists",
|
||||||
Details: &unversioned.StatusDetails{
|
Details: &unversioned.StatusDetails{
|
||||||
Kind: "foo",
|
Group: "",
|
||||||
Name: "bar",
|
Kind: "foos",
|
||||||
|
Name: "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
errors.NewConflict("foo", "bar", stderrs.New("failure")): {
|
errors.NewConflict(api.Resource("foos"), "bar", stderrs.New("failure")): {
|
||||||
Status: unversioned.StatusFailure,
|
Status: unversioned.StatusFailure,
|
||||||
Code: http.StatusConflict,
|
Code: http.StatusConflict,
|
||||||
Reason: "Conflict",
|
Reason: "Conflict",
|
||||||
Message: "foo \"bar\" cannot be updated: failure",
|
Message: "foos \"bar\" cannot be updated: failure",
|
||||||
Details: &unversioned.StatusDetails{
|
Details: &unversioned.StatusDetails{
|
||||||
Kind: "foo",
|
Group: "",
|
||||||
Name: "bar",
|
Kind: "foos",
|
||||||
|
Name: "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ func (tw *baseTimeoutWriter) timeout(msg string) {
|
|||||||
tw.w.Write([]byte(msg))
|
tw.w.Write([]byte(msg))
|
||||||
} else {
|
} else {
|
||||||
enc := json.NewEncoder(tw.w)
|
enc := json.NewEncoder(tw.w)
|
||||||
enc.Encode(errors.NewServerTimeout("", "", 0))
|
enc.Encode(errors.NewServerTimeout(api.Resource(""), "", 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tw.timedOut = true
|
tw.timedOut = true
|
||||||
|
@ -101,7 +101,7 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
redirector, ok := storage.(rest.Redirector)
|
redirector, ok := storage.(rest.Redirector)
|
||||||
if !ok {
|
if !ok {
|
||||||
httplog.LogOf(req, w).Addf("'%v' is not a redirector", resource)
|
httplog.LogOf(req, w).Addf("'%v' is not a redirector", resource)
|
||||||
httpCode = errorJSON(errors.NewMethodNotSupported(resource, "proxy"), r.codec, w)
|
httpCode = errorJSON(errors.NewMethodNotSupported(api.Resource(resource), "proxy"), r.codec, w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ func (p *testPatcher) New() runtime.Object {
|
|||||||
func (p *testPatcher) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
|
func (p *testPatcher) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
|
||||||
inPod := obj.(*api.Pod)
|
inPod := obj.(*api.Pod)
|
||||||
if inPod.ResourceVersion != p.updatePod.ResourceVersion {
|
if inPod.ResourceVersion != p.updatePod.ResourceVersion {
|
||||||
return nil, false, apierrors.NewConflict("Pod", inPod.Name, fmt.Errorf("existing %v, new %v", p.updatePod.ResourceVersion, inPod.ResourceVersion))
|
return nil, false, apierrors.NewConflict(api.Resource("pods"), inPod.Name, fmt.Errorf("existing %v, new %v", p.updatePod.ResourceVersion, inPod.ResourceVersion))
|
||||||
}
|
}
|
||||||
|
|
||||||
return inPod, false, nil
|
return inPod, false, nil
|
||||||
@ -306,7 +306,7 @@ func TestPatchResourceWithConflict(t *testing.T) {
|
|||||||
changedPod: &api.Pod{},
|
changedPod: &api.Pod{},
|
||||||
updatePod: &api.Pod{},
|
updatePod: &api.Pod{},
|
||||||
|
|
||||||
expectedError: `Pod "foo" cannot be updated: existing 2, new 1`,
|
expectedError: `pods "foo" cannot be updated: existing 2, new 1`,
|
||||||
}
|
}
|
||||||
|
|
||||||
tc.startingPod.Name = name
|
tc.startingPod.Name = name
|
||||||
|
@ -58,7 +58,7 @@ func TestTryAcquireOrRenew(t *testing.T) {
|
|||||||
{
|
{
|
||||||
verb: "get",
|
verb: "get",
|
||||||
reaction: func(action testclient.Action) (handled bool, ret runtime.Object, err error) {
|
reaction: func(action testclient.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
return true, nil, errors.NewNotFound(action.GetVerb(), action.(testclient.GetAction).GetName())
|
return true, nil, errors.NewNotFound(api.Resource(action.(testclient.GetAction).GetResource()), action.(testclient.GetAction).GetName())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -896,7 +896,7 @@ func (r *Request) transformUnstructuredResponseError(resp *http.Response, req *h
|
|||||||
message = strings.TrimSpace(string(body))
|
message = strings.TrimSpace(string(body))
|
||||||
}
|
}
|
||||||
retryAfter, _ := retryAfterSeconds(resp)
|
retryAfter, _ := retryAfterSeconds(resp)
|
||||||
return errors.NewGenericServerResponse(resp.StatusCode, req.Method, r.resource, r.resourceName, message, retryAfter, true)
|
return errors.NewGenericServerResponse(resp.StatusCode, req.Method, unversioned.GroupResource{Group: r.groupVersion.Group, Resource: r.resource}, r.resourceName, message, retryAfter, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isTextResponse returns true if the response appears to be a textual media type.
|
// isTextResponse returns true if the response appears to be a textual media type.
|
||||||
|
@ -181,7 +181,7 @@ func (o objects) Kind(kind unversioned.GroupVersionKind, name string) (runtime.O
|
|||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
return nilValue, errors.NewNotFound(kind.Kind, name)
|
return nilValue, errors.NewNotFound(unversioned.GroupResource{Group: kind.Group, Resource: kind.Kind}, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
index := o.last[kind.Kind]
|
index := o.last[kind.Kind]
|
||||||
@ -189,7 +189,7 @@ func (o objects) Kind(kind unversioned.GroupVersionKind, name string) (runtime.O
|
|||||||
index = len(arr) - 1
|
index = len(arr) - 1
|
||||||
}
|
}
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
return nilValue, errors.NewNotFound(kind.Kind, name)
|
return nilValue, errors.NewNotFound(unversioned.GroupResource{Group: kind.Group, Resource: kind.Kind}, name)
|
||||||
}
|
}
|
||||||
out, err := o.scheme.Copy(arr[index])
|
out, err := o.scheme.Copy(arr[index])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -56,9 +56,9 @@ func TestErrors(t *testing.T) {
|
|||||||
o.Add(&api.List{
|
o.Add(&api.List{
|
||||||
Items: []runtime.Object{
|
Items: []runtime.Object{
|
||||||
// This first call to List will return this error
|
// This first call to List will return this error
|
||||||
&(errors.NewNotFound("ServiceList", "").(*errors.StatusError).ErrStatus),
|
&(errors.NewNotFound(api.Resource("ServiceList"), "").(*errors.StatusError).ErrStatus),
|
||||||
// The second call to List will return this error
|
// The second call to List will return this error
|
||||||
&(errors.NewForbidden("ServiceList", "", nil).(*errors.StatusError).ErrStatus),
|
&(errors.NewForbidden(api.Resource("ServiceList"), "", nil).(*errors.StatusError).ErrStatus),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
client := &Fake{}
|
client := &Fake{}
|
||||||
|
@ -180,7 +180,7 @@ func TestRetryOnConflictError(t *testing.T) {
|
|||||||
retryOnce := func(kubeClient client.Interface, namespace *api.Namespace) (*api.Namespace, error) {
|
retryOnce := func(kubeClient client.Interface, namespace *api.Namespace) (*api.Namespace, error) {
|
||||||
numTries++
|
numTries++
|
||||||
if numTries <= 1 {
|
if numTries <= 1 {
|
||||||
return namespace, errors.NewConflict(namespace.Kind, namespace.Name, fmt.Errorf("ERROR!"))
|
return namespace, errors.NewConflict(api.Resource("namespaces"), namespace.Name, fmt.Errorf("ERROR!"))
|
||||||
}
|
}
|
||||||
return namespace, nil
|
return namespace, nil
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func (m *FakeNodeHandler) Create(node *api.Node) (*api.Node, error) {
|
|||||||
}()
|
}()
|
||||||
for _, n := range m.Existing {
|
for _, n := range m.Existing {
|
||||||
if n.Name == node.Name {
|
if n.Name == node.Name {
|
||||||
return nil, apierrors.NewAlreadyExists("Node", node.Name)
|
return nil, apierrors.NewAlreadyExists(api.Resource("nodes"), node.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m.CreateHook == nil || m.CreateHook(m, node) {
|
if m.CreateHook == nil || m.CreateHook(m, node) {
|
||||||
|
@ -419,7 +419,7 @@ func (c *mockBinderClient) GetPersistentVolumeClaim(namespace, name string) (*ap
|
|||||||
if c.claim != nil {
|
if c.claim != nil {
|
||||||
return c.claim, nil
|
return c.claim, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.NewNotFound("persistentVolume", name)
|
return nil, errors.NewNotFound(api.Resource("persistentvolumes"), name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ func (c *mockControllerClient) GetPersistentVolumeClaim(namespace, name string)
|
|||||||
if c.claim != nil {
|
if c.claim != nil {
|
||||||
return c.claim, nil
|
return c.claim, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.NewNotFound("persistentVolume", name)
|
return nil, errors.NewNotFound(api.Resource("persistentvolumes"), name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ func TestDeleteAllNotFound(t *testing.T) {
|
|||||||
|
|
||||||
// Add an item to the list which will result in a 404 on delete
|
// Add an item to the list which will result in a 404 on delete
|
||||||
svc.Items = append(svc.Items, api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}})
|
svc.Items = append(svc.Items, api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}})
|
||||||
notFoundError := &errors.NewNotFound("Service", "foo").(*errors.StatusError).ErrStatus
|
notFoundError := &errors.NewNotFound(api.Resource("services"), "foo").(*errors.StatusError).ErrStatus
|
||||||
|
|
||||||
tf.Printer = &testPrinter{}
|
tf.Printer = &testPrinter{}
|
||||||
tf.Client = &fake.RESTClient{
|
tf.Client = &fake.RESTClient{
|
||||||
@ -234,7 +234,7 @@ func TestDeleteAllIgnoreNotFound(t *testing.T) {
|
|||||||
|
|
||||||
// Add an item to the list which will result in a 404 on delete
|
// Add an item to the list which will result in a 404 on delete
|
||||||
svc.Items = append(svc.Items, api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}})
|
svc.Items = append(svc.Items, api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}})
|
||||||
notFoundError := &errors.NewNotFound("Service", "foo").(*errors.StatusError).ErrStatus
|
notFoundError := &errors.NewNotFound(api.Resource("services"), "foo").(*errors.StatusError).ErrStatus
|
||||||
|
|
||||||
tf.Printer = &testPrinter{}
|
tf.Printer = &testPrinter{}
|
||||||
tf.Client = &fake.RESTClient{
|
tf.Client = &fake.RESTClient{
|
||||||
|
@ -274,15 +274,15 @@ func TestCheckInvalidErr(t *testing.T) {
|
|||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
errors.NewInvalid("Invalid1", "invalidation", field.ErrorList{field.Invalid(field.NewPath("field"), "single", "details")}),
|
errors.NewInvalid(api.Kind("Invalid1"), "invalidation", field.ErrorList{field.Invalid(field.NewPath("field"), "single", "details")}),
|
||||||
`Error from server: Invalid1 "invalidation" is invalid: field: invalid value 'single', Details: details`,
|
`Error from server: Invalid1 "invalidation" is invalid: field: invalid value 'single', Details: details`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
errors.NewInvalid("Invalid2", "invalidation", field.ErrorList{field.Invalid(field.NewPath("field1"), "multi1", "details"), field.Invalid(field.NewPath("field2"), "multi2", "details")}),
|
errors.NewInvalid(api.Kind("Invalid2"), "invalidation", field.ErrorList{field.Invalid(field.NewPath("field1"), "multi1", "details"), field.Invalid(field.NewPath("field2"), "multi2", "details")}),
|
||||||
`Error from server: Invalid2 "invalidation" is invalid: [field1: invalid value 'multi1', Details: details, field2: invalid value 'multi2', Details: details]`,
|
`Error from server: Invalid2 "invalidation" is invalid: [field1: invalid value 'multi1', Details: details, field2: invalid value 'multi2', Details: details]`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
errors.NewInvalid("Invalid3", "invalidation", field.ErrorList{}),
|
errors.NewInvalid(api.Kind("Invalid3"), "invalidation", field.ErrorList{}),
|
||||||
`Error from server: Invalid3 "invalidation" is invalid: <nil>`,
|
`Error from server: Invalid3 "invalidation" is invalid: <nil>`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -431,7 +431,7 @@ func (r *RollingUpdater) getOrCreateTargetControllerWithClient(controller *api.R
|
|||||||
func (r *RollingUpdater) existingController(controller *api.ReplicationController) (*api.ReplicationController, error) {
|
func (r *RollingUpdater) existingController(controller *api.ReplicationController) (*api.ReplicationController, error) {
|
||||||
// without rc name but generate name, there's no existing rc
|
// without rc name but generate name, there's no existing rc
|
||||||
if len(controller.Name) == 0 && len(controller.GenerateName) > 0 {
|
if len(controller.Name) == 0 && len(controller.GenerateName) > 0 {
|
||||||
return nil, errors.NewNotFound("ReplicationController", controller.Name)
|
return nil, errors.NewNotFound(api.Resource("replicationcontrollers"), controller.Name)
|
||||||
}
|
}
|
||||||
// controller name is required to get rc back
|
// controller name is required to get rc back
|
||||||
return r.c.ReplicationControllers(controller.Namespace).Get(controller.Name)
|
return r.c.ReplicationControllers(controller.Namespace).Get(controller.Name)
|
||||||
|
@ -34,7 +34,7 @@ type ErrorReplicationControllers struct {
|
|||||||
|
|
||||||
func (c *ErrorReplicationControllers) Update(controller *api.ReplicationController) (*api.ReplicationController, error) {
|
func (c *ErrorReplicationControllers) Update(controller *api.ReplicationController) (*api.ReplicationController, error) {
|
||||||
if c.invalid {
|
if c.invalid {
|
||||||
return nil, kerrors.NewInvalid(controller.Kind, controller.Name, nil)
|
return nil, kerrors.NewInvalid(api.Kind(controller.Kind), controller.Name, nil)
|
||||||
}
|
}
|
||||||
return nil, errors.New("Replication controller update failure")
|
return nil, errors.New("Replication controller update failure")
|
||||||
}
|
}
|
||||||
@ -254,7 +254,7 @@ type ErrorJobs struct {
|
|||||||
|
|
||||||
func (c *ErrorJobs) Update(job *extensions.Job) (*extensions.Job, error) {
|
func (c *ErrorJobs) Update(job *extensions.Job) (*extensions.Job, error) {
|
||||||
if c.invalid {
|
if c.invalid {
|
||||||
return nil, kerrors.NewInvalid(job.Kind, job.Name, nil)
|
return nil, kerrors.NewInvalid(extensions.Kind(job.Kind), job.Name, nil)
|
||||||
}
|
}
|
||||||
return nil, errors.New("Job update failure")
|
return nil, errors.New("Job update failure")
|
||||||
}
|
}
|
||||||
@ -495,7 +495,7 @@ type ErrorScales struct {
|
|||||||
|
|
||||||
func (c *ErrorScales) Update(kind string, scale *extensions.Scale) (*extensions.Scale, error) {
|
func (c *ErrorScales) Update(kind string, scale *extensions.Scale) (*extensions.Scale, error) {
|
||||||
if c.invalid {
|
if c.invalid {
|
||||||
return nil, kerrors.NewInvalid(scale.Kind, scale.Name, nil)
|
return nil, kerrors.NewInvalid(extensions.Kind(scale.Kind), scale.Name, nil)
|
||||||
}
|
}
|
||||||
return nil, errors.New("scale update failure")
|
return nil, errors.New("scale update failure")
|
||||||
}
|
}
|
||||||
@ -515,7 +515,7 @@ type ErrorDeployments struct {
|
|||||||
|
|
||||||
func (c *ErrorDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) {
|
func (c *ErrorDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) {
|
||||||
if c.invalid {
|
if c.invalid {
|
||||||
return nil, kerrors.NewInvalid(deployment.Kind, deployment.Name, nil)
|
return nil, kerrors.NewInvalid(extensions.Kind(deployment.Kind), deployment.Name, nil)
|
||||||
}
|
}
|
||||||
return nil, errors.New("deployment update failure")
|
return nil, errors.New("deployment update failure")
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ func TestSyncBatchIgnoresNotFound(t *testing.T) {
|
|||||||
client := testclient.Fake{}
|
client := testclient.Fake{}
|
||||||
syncer := newTestManager(&client)
|
syncer := newTestManager(&client)
|
||||||
client.AddReactor("get", "pods", func(action testclient.Action) (bool, runtime.Object, error) {
|
client.AddReactor("get", "pods", func(action testclient.Action) (bool, runtime.Object, error) {
|
||||||
return true, nil, errors.NewNotFound("pods", "test-pod")
|
return true, nil, errors.NewNotFound(api.Resource("pods"), "test-pod")
|
||||||
})
|
})
|
||||||
syncer.SetPodStatus(testPod, getRandomPodStatus())
|
syncer.SetPodStatus(testPod, getRandomPodStatus())
|
||||||
syncer.syncBatch()
|
syncer.syncBatch()
|
||||||
@ -322,7 +322,7 @@ func TestSyncBatchNoDeadlock(t *testing.T) {
|
|||||||
|
|
||||||
// Pod not found.
|
// Pod not found.
|
||||||
ret = *pod
|
ret = *pod
|
||||||
err = errors.NewNotFound("pods", pod.Name)
|
err = errors.NewNotFound(api.Resource("pods"), pod.Name)
|
||||||
m.SetPodStatus(pod, getRandomPodStatus())
|
m.SetPodStatus(pod, getRandomPodStatus())
|
||||||
m.syncBatch()
|
m.syncBatch()
|
||||||
verifyActions(t, client, []testclient.Action{getAction})
|
verifyActions(t, client, []testclient.Action{getAction})
|
||||||
|
@ -262,7 +262,7 @@ func (m *Master) initV1ResourcesStorage(c *Config) {
|
|||||||
}
|
}
|
||||||
serviceClusterIPAllocator := ipallocator.NewAllocatorCIDRRange(serviceClusterIPRange, func(max int, rangeSpec string) allocator.Interface {
|
serviceClusterIPAllocator := ipallocator.NewAllocatorCIDRRange(serviceClusterIPRange, func(max int, rangeSpec string) allocator.Interface {
|
||||||
mem := allocator.NewAllocationMap(max, rangeSpec)
|
mem := allocator.NewAllocationMap(max, rangeSpec)
|
||||||
etcd := etcdallocator.NewEtcd(mem, "/ranges/serviceips", "serviceipallocation", dbClient("services"))
|
etcd := etcdallocator.NewEtcd(mem, "/ranges/serviceips", api.Resource("serviceipallocations"), dbClient("services"))
|
||||||
serviceClusterIPRegistry = etcd
|
serviceClusterIPRegistry = etcd
|
||||||
return etcd
|
return etcd
|
||||||
})
|
})
|
||||||
@ -271,7 +271,7 @@ func (m *Master) initV1ResourcesStorage(c *Config) {
|
|||||||
var serviceNodePortRegistry service.RangeRegistry
|
var serviceNodePortRegistry service.RangeRegistry
|
||||||
serviceNodePortAllocator := portallocator.NewPortAllocatorCustom(m.ServiceNodePortRange, func(max int, rangeSpec string) allocator.Interface {
|
serviceNodePortAllocator := portallocator.NewPortAllocatorCustom(m.ServiceNodePortRange, func(max int, rangeSpec string) allocator.Interface {
|
||||||
mem := allocator.NewAllocationMap(max, rangeSpec)
|
mem := allocator.NewAllocationMap(max, rangeSpec)
|
||||||
etcd := etcdallocator.NewEtcd(mem, "/ranges/servicenodeports", "servicenodeportallocation", dbClient("services"))
|
etcd := etcdallocator.NewEtcd(mem, "/ranges/servicenodeports", api.Resource("servicenodeportallocations"), dbClient("services"))
|
||||||
serviceNodePortRegistry = etcd
|
serviceNodePortRegistry = etcd
|
||||||
return etcd
|
return etcd
|
||||||
})
|
})
|
||||||
|
@ -68,7 +68,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
|
|||||||
// Matches objects based on labels/fields for list and watch
|
// Matches objects based on labels/fields for list and watch
|
||||||
PredicateFunc: configmap.MatchConfigMap,
|
PredicateFunc: configmap.MatchConfigMap,
|
||||||
|
|
||||||
EndpointName: "configmaps",
|
QualifiedResource: extensions.Resource("configmaps"),
|
||||||
|
|
||||||
CreateStrategy: configmap.Strategy,
|
CreateStrategy: configmap.Strategy,
|
||||||
UpdateStrategy: configmap.Strategy,
|
UpdateStrategy: configmap.Strategy,
|
||||||
|
@ -62,7 +62,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return controller.MatchController(label, field)
|
return controller.MatchController(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "replicationControllers",
|
QualifiedResource: api.Resource("replicationcontrollers"),
|
||||||
|
|
||||||
// Used to validate controller creation
|
// Used to validate controller creation
|
||||||
CreateStrategy: controller.Strategy,
|
CreateStrategy: controller.Strategy,
|
||||||
|
@ -64,7 +64,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return daemonset.MatchDaemonSet(label, field)
|
return daemonset.MatchDaemonSet(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "daemonsets",
|
QualifiedResource: extensions.Resource("daemonsets"),
|
||||||
|
|
||||||
// Used to validate daemon set creation
|
// Used to validate daemon set creation
|
||||||
CreateStrategy: daemonset.Strategy,
|
CreateStrategy: daemonset.Strategy,
|
||||||
|
@ -86,7 +86,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return deployment.MatchDeployment(label, field)
|
return deployment.MatchDeployment(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "deployments",
|
QualifiedResource: extensions.Resource("deployments"),
|
||||||
|
|
||||||
// Used to validate deployment creation.
|
// Used to validate deployment creation.
|
||||||
CreateStrategy: deployment.Strategy,
|
CreateStrategy: deployment.Strategy,
|
||||||
@ -130,7 +130,7 @@ func (r *ScaleREST) New() runtime.Object {
|
|||||||
func (r *ScaleREST) Get(ctx api.Context, name string) (runtime.Object, error) {
|
func (r *ScaleREST) Get(ctx api.Context, name string) (runtime.Object, error) {
|
||||||
deployment, err := (*r.registry).GetDeployment(ctx, name)
|
deployment, err := (*r.registry).GetDeployment(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.NewNotFound("scale", name)
|
return nil, errors.NewNotFound(extensions.Resource("deployments/scale"), name)
|
||||||
}
|
}
|
||||||
return extensions.ScaleFromDeployment(deployment), nil
|
return extensions.ScaleFromDeployment(deployment), nil
|
||||||
}
|
}
|
||||||
@ -145,17 +145,17 @@ func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if errs := extvalidation.ValidateScale(scale); len(errs) > 0 {
|
if errs := extvalidation.ValidateScale(scale); len(errs) > 0 {
|
||||||
return nil, false, errors.NewInvalid("scale", scale.Name, errs)
|
return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
deployment, err := (*r.registry).GetDeployment(ctx, scale.Name)
|
deployment, err := (*r.registry).GetDeployment(ctx, scale.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, errors.NewNotFound("scale", scale.Name)
|
return nil, false, errors.NewNotFound(extensions.Resource("deployments/scale"), scale.Name)
|
||||||
}
|
}
|
||||||
deployment.Spec.Replicas = scale.Spec.Replicas
|
deployment.Spec.Replicas = scale.Spec.Replicas
|
||||||
deployment, err = (*r.registry).UpdateDeployment(ctx, deployment)
|
deployment, err = (*r.registry).UpdateDeployment(ctx, deployment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, errors.NewConflict("scale", scale.Name, err)
|
return nil, false, errors.NewConflict(extensions.Resource("deployments/scale"), scale.Name, err)
|
||||||
}
|
}
|
||||||
return extensions.ScaleFromDeployment(deployment), false, nil
|
return extensions.ScaleFromDeployment(deployment), false, nil
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return endpoint.MatchEndpoints(label, field)
|
return endpoint.MatchEndpoints(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "endpoints",
|
QualifiedResource: api.Resource("endpoints"),
|
||||||
|
|
||||||
CreateStrategy: endpoint.Strategy,
|
CreateStrategy: endpoint.Strategy,
|
||||||
UpdateStrategy: endpoint.Strategy,
|
UpdateStrategy: endpoint.Strategy,
|
||||||
|
@ -57,7 +57,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator, ttl
|
|||||||
TTLFunc: func(runtime.Object, uint64, bool) (uint64, error) {
|
TTLFunc: func(runtime.Object, uint64, bool) (uint64, error) {
|
||||||
return ttl, nil
|
return ttl, nil
|
||||||
},
|
},
|
||||||
EndpointName: "events",
|
QualifiedResource: api.Resource("events"),
|
||||||
|
|
||||||
CreateStrategy: event.Strategy,
|
CreateStrategy: event.Strategy,
|
||||||
UpdateStrategy: event.Strategy,
|
UpdateStrategy: event.Strategy,
|
||||||
|
@ -66,7 +66,7 @@ func (r *ScaleREST) New() runtime.Object {
|
|||||||
func (r *ScaleREST) Get(ctx api.Context, name string) (runtime.Object, error) {
|
func (r *ScaleREST) Get(ctx api.Context, name string) (runtime.Object, error) {
|
||||||
rc, err := (*r.registry).GetController(ctx, name)
|
rc, err := (*r.registry).GetController(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.NewNotFound("scale", name)
|
return nil, errors.NewNotFound(extensions.Resource("replicationcontrollers/scale"), name)
|
||||||
}
|
}
|
||||||
return &extensions.Scale{
|
return &extensions.Scale{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
@ -94,17 +94,17 @@ func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if errs := extvalidation.ValidateScale(scale); len(errs) > 0 {
|
if errs := extvalidation.ValidateScale(scale); len(errs) > 0 {
|
||||||
return nil, false, errors.NewInvalid("scale", scale.Name, errs)
|
return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := (*r.registry).GetController(ctx, scale.Name)
|
rc, err := (*r.registry).GetController(ctx, scale.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, errors.NewNotFound("scale", scale.Name)
|
return nil, false, errors.NewNotFound(extensions.Resource("replicationcontrollers/scale"), scale.Name)
|
||||||
}
|
}
|
||||||
rc.Spec.Replicas = scale.Spec.Replicas
|
rc.Spec.Replicas = scale.Spec.Replicas
|
||||||
rc, err = (*r.registry).UpdateController(ctx, rc)
|
rc, err = (*r.registry).UpdateController(ctx, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, errors.NewConflict("scale", scale.Name, err)
|
return nil, false, errors.NewConflict(extensions.Resource("replicationcontrollers/scale"), scale.Name, err)
|
||||||
}
|
}
|
||||||
return &extensions.Scale{
|
return &extensions.Scale{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
@ -63,7 +63,7 @@ type Etcd struct {
|
|||||||
NewListFunc func() runtime.Object
|
NewListFunc func() runtime.Object
|
||||||
|
|
||||||
// Used for error reporting
|
// Used for error reporting
|
||||||
EndpointName string
|
QualifiedResource unversioned.GroupResource
|
||||||
|
|
||||||
// Used for listing/watching; should not include trailing "/"
|
// Used for listing/watching; should not include trailing "/"
|
||||||
KeyRootFunc func(ctx api.Context) string
|
KeyRootFunc func(ctx api.Context) string
|
||||||
@ -181,7 +181,7 @@ func (e *Etcd) ListPredicate(ctx api.Context, m generic.Matcher, options *unvers
|
|||||||
if name, ok := m.MatchesSingle(); ok {
|
if name, ok := m.MatchesSingle(); ok {
|
||||||
if key, err := e.KeyFunc(ctx, name); err == nil {
|
if key, err := e.KeyFunc(ctx, name); err == nil {
|
||||||
err := e.Storage.GetToList(ctx, key, filterFunc, list)
|
err := e.Storage.GetToList(ctx, key, filterFunc, list)
|
||||||
return list, etcderr.InterpretListError(err, e.EndpointName)
|
return list, etcderr.InterpretListError(err, e.QualifiedResource)
|
||||||
}
|
}
|
||||||
// if we cannot extract a key based on the current context, the optimization is skipped
|
// if we cannot extract a key based on the current context, the optimization is skipped
|
||||||
}
|
}
|
||||||
@ -190,7 +190,7 @@ func (e *Etcd) ListPredicate(ctx api.Context, m generic.Matcher, options *unvers
|
|||||||
options = &unversioned.ListOptions{ResourceVersion: "0"}
|
options = &unversioned.ListOptions{ResourceVersion: "0"}
|
||||||
}
|
}
|
||||||
err := e.Storage.List(ctx, e.KeyRootFunc(ctx), options.ResourceVersion, filterFunc, list)
|
err := e.Storage.List(ctx, e.KeyRootFunc(ctx), options.ResourceVersion, filterFunc, list)
|
||||||
return list, etcderr.InterpretListError(err, e.EndpointName)
|
return list, etcderr.InterpretListError(err, e.QualifiedResource)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create inserts a new item according to the unique key from the object.
|
// Create inserts a new item according to the unique key from the object.
|
||||||
@ -212,7 +212,7 @@ func (e *Etcd) Create(ctx api.Context, obj runtime.Object) (runtime.Object, erro
|
|||||||
}
|
}
|
||||||
out := e.NewFunc()
|
out := e.NewFunc()
|
||||||
if err := e.Storage.Create(ctx, key, obj, out, ttl); err != nil {
|
if err := e.Storage.Create(ctx, key, obj, out, ttl); err != nil {
|
||||||
err = etcderr.InterpretCreateError(err, e.EndpointName, name)
|
err = etcderr.InterpretCreateError(err, e.QualifiedResource, name)
|
||||||
err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj)
|
err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -259,7 +259,7 @@ func (e *Etcd) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool
|
|||||||
}
|
}
|
||||||
if version == 0 {
|
if version == 0 {
|
||||||
if !e.UpdateStrategy.AllowCreateOnUpdate() {
|
if !e.UpdateStrategy.AllowCreateOnUpdate() {
|
||||||
return nil, nil, kubeerr.NewNotFound(e.EndpointName, name)
|
return nil, nil, kubeerr.NewNotFound(e.QualifiedResource, name)
|
||||||
}
|
}
|
||||||
creating = true
|
creating = true
|
||||||
if err := rest.BeforeCreate(e.CreateStrategy, ctx, obj); err != nil {
|
if err := rest.BeforeCreate(e.CreateStrategy, ctx, obj); err != nil {
|
||||||
@ -286,7 +286,7 @@ func (e *Etcd) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if newVersion != version {
|
if newVersion != version {
|
||||||
return nil, nil, kubeerr.NewConflict(e.EndpointName, name, fmt.Errorf("the object has been modified; please apply your changes to the latest version and try again"))
|
return nil, nil, kubeerr.NewConflict(e.QualifiedResource, name, fmt.Errorf("the object has been modified; please apply your changes to the latest version and try again"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := rest.BeforeUpdate(e.UpdateStrategy, ctx, obj, existing); err != nil {
|
if err := rest.BeforeUpdate(e.UpdateStrategy, ctx, obj, existing); err != nil {
|
||||||
@ -304,10 +304,10 @@ func (e *Etcd) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if creating {
|
if creating {
|
||||||
err = etcderr.InterpretCreateError(err, e.EndpointName, name)
|
err = etcderr.InterpretCreateError(err, e.QualifiedResource, name)
|
||||||
err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj)
|
err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj)
|
||||||
} else {
|
} else {
|
||||||
err = etcderr.InterpretUpdateError(err, e.EndpointName, name)
|
err = etcderr.InterpretUpdateError(err, e.QualifiedResource, name)
|
||||||
}
|
}
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
@ -340,7 +340,7 @@ func (e *Etcd) Get(ctx api.Context, name string) (runtime.Object, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := e.Storage.Get(ctx, key, obj, false); err != nil {
|
if err := e.Storage.Get(ctx, key, obj, false); err != nil {
|
||||||
return nil, etcderr.InterpretGetError(err, e.EndpointName, name)
|
return nil, etcderr.InterpretGetError(err, e.QualifiedResource, name)
|
||||||
}
|
}
|
||||||
if e.Decorator != nil {
|
if e.Decorator != nil {
|
||||||
if err := e.Decorator(obj); err != nil {
|
if err := e.Decorator(obj); err != nil {
|
||||||
@ -364,7 +364,7 @@ func (e *Etcd) Delete(ctx api.Context, name string, options *api.DeleteOptions)
|
|||||||
|
|
||||||
obj := e.NewFunc()
|
obj := e.NewFunc()
|
||||||
if err := e.Storage.Get(ctx, key, obj, false); err != nil {
|
if err := e.Storage.Get(ctx, key, obj, false); err != nil {
|
||||||
return nil, etcderr.InterpretDeleteError(err, e.EndpointName, name)
|
return nil, etcderr.InterpretDeleteError(err, e.QualifiedResource, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// support older consumers of delete by treating "nil" as delete immediately
|
// support older consumers of delete by treating "nil" as delete immediately
|
||||||
@ -410,14 +410,14 @@ func (e *Etcd) Delete(ctx api.Context, name string, options *api.DeleteOptions)
|
|||||||
case errAlreadyDeleting:
|
case errAlreadyDeleting:
|
||||||
return e.finalizeDelete(obj, true)
|
return e.finalizeDelete(obj, true)
|
||||||
default:
|
default:
|
||||||
return nil, etcderr.InterpretUpdateError(err, e.EndpointName, name)
|
return nil, etcderr.InterpretUpdateError(err, e.QualifiedResource, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete immediately, or no graceful deletion supported
|
// delete immediately, or no graceful deletion supported
|
||||||
out := e.NewFunc()
|
out := e.NewFunc()
|
||||||
if err := e.Storage.Delete(ctx, key, out); err != nil {
|
if err := e.Storage.Delete(ctx, key, out); err != nil {
|
||||||
return nil, etcderr.InterpretDeleteError(err, e.EndpointName, name)
|
return nil, etcderr.InterpretDeleteError(err, e.QualifiedResource, name)
|
||||||
}
|
}
|
||||||
return e.finalizeDelete(out, true)
|
return e.finalizeDelete(out, true)
|
||||||
}
|
}
|
||||||
|
@ -92,11 +92,11 @@ func NewTestGenericEtcdRegistry(t *testing.T) (*etcdtesting.EtcdTestServer, *Etc
|
|||||||
strategy := &testRESTStrategy{api.Scheme, api.SimpleNameGenerator, true, false, true}
|
strategy := &testRESTStrategy{api.Scheme, api.SimpleNameGenerator, true, false, true}
|
||||||
|
|
||||||
return server, &Etcd{
|
return server, &Etcd{
|
||||||
NewFunc: func() runtime.Object { return &api.Pod{} },
|
NewFunc: func() runtime.Object { return &api.Pod{} },
|
||||||
NewListFunc: func() runtime.Object { return &api.PodList{} },
|
NewListFunc: func() runtime.Object { return &api.PodList{} },
|
||||||
EndpointName: "pods",
|
QualifiedResource: api.Resource("pods"),
|
||||||
CreateStrategy: strategy,
|
CreateStrategy: strategy,
|
||||||
UpdateStrategy: strategy,
|
UpdateStrategy: strategy,
|
||||||
KeyRootFunc: func(ctx api.Context) string {
|
KeyRootFunc: func(ctx api.Context) string {
|
||||||
return podPrefix
|
return podPrefix
|
||||||
},
|
},
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check the http error status from a location URL.
|
// Check the http error status from a location URL.
|
||||||
@ -39,8 +40,8 @@ const (
|
|||||||
|
|
||||||
// A generic http response checker to transform the error.
|
// A generic http response checker to transform the error.
|
||||||
type GenericHttpResponseChecker struct {
|
type GenericHttpResponseChecker struct {
|
||||||
Kind string
|
QualifiedResource unversioned.GroupResource
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (checker GenericHttpResponseChecker) Check(resp *http.Response) error {
|
func (checker GenericHttpResponseChecker) Check(resp *http.Response) error {
|
||||||
@ -58,13 +59,13 @@ func (checker GenericHttpResponseChecker) Check(resp *http.Response) error {
|
|||||||
case resp.StatusCode == http.StatusBadRequest:
|
case resp.StatusCode == http.StatusBadRequest:
|
||||||
return errors.NewBadRequest(bodyText)
|
return errors.NewBadRequest(bodyText)
|
||||||
case resp.StatusCode == http.StatusNotFound:
|
case resp.StatusCode == http.StatusNotFound:
|
||||||
return errors.NewGenericServerResponse(resp.StatusCode, "", checker.Kind, checker.Name, bodyText, 0, false)
|
return errors.NewGenericServerResponse(resp.StatusCode, "", checker.QualifiedResource, checker.Name, bodyText, 0, false)
|
||||||
}
|
}
|
||||||
return errors.NewGenericServerResponse(resp.StatusCode, "", checker.Kind, checker.Name, bodyText, 0, false)
|
return errors.NewGenericServerResponse(resp.StatusCode, "", checker.QualifiedResource, checker.Name, bodyText, 0, false)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGenericHttpResponseChecker(kind, name string) GenericHttpResponseChecker {
|
func NewGenericHttpResponseChecker(qualifiedResource unversioned.GroupResource, name string) GenericHttpResponseChecker {
|
||||||
return GenericHttpResponseChecker{Kind: kind, Name: name}
|
return GenericHttpResponseChecker{QualifiedResource: qualifiedResource, Name: name}
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGenericHttpResponseChecker(t *testing.T) {
|
func TestGenericHttpResponseChecker(t *testing.T) {
|
||||||
responseChecker := NewGenericHttpResponseChecker("Pod", "foo")
|
responseChecker := NewGenericHttpResponseChecker(api.Resource("pods"), "foo")
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
resp *http.Response
|
resp *http.Response
|
||||||
expectError bool
|
expectError bool
|
||||||
@ -78,7 +79,7 @@ func TestGenericHttpResponseChecker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGenericHttpResponseCheckerLimitReader(t *testing.T) {
|
func TestGenericHttpResponseCheckerLimitReader(t *testing.T) {
|
||||||
responseChecker := NewGenericHttpResponseChecker("Pod", "foo")
|
responseChecker := NewGenericHttpResponseChecker(api.Resource("pods"), "foo")
|
||||||
excessedString := strings.Repeat("a", (maxReadLength + 10000))
|
excessedString := strings.Repeat("a", (maxReadLength + 10000))
|
||||||
resp := &http.Response{
|
resp := &http.Response{
|
||||||
Body: ioutil.NopCloser(bytes.NewBufferString(excessedString)),
|
Body: ioutil.NopCloser(bytes.NewBufferString(excessedString)),
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -131,7 +132,7 @@ func TestInputStreamInternalServerErrorTransport(t *testing.T) {
|
|||||||
streamer := &LocationStreamer{
|
streamer := &LocationStreamer{
|
||||||
Location: location,
|
Location: location,
|
||||||
Transport: fakeInternalServerErrorTransport("text/plain", message),
|
Transport: fakeInternalServerErrorTransport("text/plain", message),
|
||||||
ResponseChecker: NewGenericHttpResponseChecker("", ""),
|
ResponseChecker: NewGenericHttpResponseChecker(api.Resource(""), ""),
|
||||||
}
|
}
|
||||||
expectedError := errors.NewInternalError(fmt.Errorf("%s", message))
|
expectedError := errors.NewInternalError(fmt.Errorf("%s", message))
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return horizontalpodautoscaler.MatchAutoscaler(label, field)
|
return horizontalpodautoscaler.MatchAutoscaler(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "horizontalPodAutoscalers",
|
QualifiedResource: extensions.Resource("horizontalpodautoscalers"),
|
||||||
|
|
||||||
// Used to validate autoscaler creation
|
// Used to validate autoscaler creation
|
||||||
CreateStrategy: horizontalpodautoscaler.Strategy,
|
CreateStrategy: horizontalpodautoscaler.Strategy,
|
||||||
|
@ -64,7 +64,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return ingress.MatchIngress(label, field)
|
return ingress.MatchIngress(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "ingresses",
|
QualifiedResource: extensions.Resource("ingresses"),
|
||||||
|
|
||||||
// Used to validate controller creation
|
// Used to validate controller creation
|
||||||
CreateStrategy: ingress.Strategy,
|
CreateStrategy: ingress.Strategy,
|
||||||
|
@ -64,7 +64,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return job.MatchJob(label, field)
|
return job.MatchJob(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "jobs",
|
QualifiedResource: extensions.Resource("jobs"),
|
||||||
|
|
||||||
// Used to validate job creation
|
// Used to validate job creation
|
||||||
CreateStrategy: job.Strategy,
|
CreateStrategy: job.Strategy,
|
||||||
|
@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return limitrange.MatchLimitRange(label, field)
|
return limitrange.MatchLimitRange(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "limitranges",
|
QualifiedResource: api.Resource("limitranges"),
|
||||||
|
|
||||||
CreateStrategy: limitrange.Strategy,
|
CreateStrategy: limitrange.Strategy,
|
||||||
UpdateStrategy: limitrange.Strategy,
|
UpdateStrategy: limitrange.Strategy,
|
||||||
|
@ -70,7 +70,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return namespace.MatchNamespace(label, field)
|
return namespace.MatchNamespace(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "namespaces",
|
QualifiedResource: api.Resource("namespaces"),
|
||||||
|
|
||||||
CreateStrategy: namespace.Strategy,
|
CreateStrategy: namespace.Strategy,
|
||||||
UpdateStrategy: namespace.Strategy,
|
UpdateStrategy: namespace.Strategy,
|
||||||
@ -108,7 +108,7 @@ func (r *REST) Delete(ctx api.Context, name string, options *api.DeleteOptions)
|
|||||||
|
|
||||||
// prior to final deletion, we must ensure that finalizers is empty
|
// prior to final deletion, we must ensure that finalizers is empty
|
||||||
if len(namespace.Spec.Finalizers) != 0 {
|
if len(namespace.Spec.Finalizers) != 0 {
|
||||||
err = apierrors.NewConflict("Namespace", namespace.Name, fmt.Errorf("The system is ensuring all content is removed from this namespace. Upon completion, this namespace will automatically be purged by the system."))
|
err = apierrors.NewConflict(api.Resource("namespaces"), namespace.Name, fmt.Errorf("The system is ensuring all content is removed from this namespace. Upon completion, this namespace will automatically be purged by the system."))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return r.Etcd.Delete(ctx, name, nil)
|
return r.Etcd.Delete(ctx, name, nil)
|
||||||
|
@ -71,8 +71,8 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator, con
|
|||||||
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||||
return obj.(*api.Node).Name, nil
|
return obj.(*api.Node).Name, nil
|
||||||
},
|
},
|
||||||
PredicateFunc: node.MatchNode,
|
PredicateFunc: node.MatchNode,
|
||||||
EndpointName: "node",
|
QualifiedResource: api.Resource("nodes"),
|
||||||
|
|
||||||
CreateStrategy: node.Strategy,
|
CreateStrategy: node.Strategy,
|
||||||
UpdateStrategy: node.Strategy,
|
UpdateStrategy: node.Strategy,
|
||||||
|
@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return persistentvolume.MatchPersistentVolumes(label, field)
|
return persistentvolume.MatchPersistentVolumes(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "persistentvolume",
|
QualifiedResource: api.Resource("persistentvolumes"),
|
||||||
|
|
||||||
CreateStrategy: persistentvolume.Strategy,
|
CreateStrategy: persistentvolume.Strategy,
|
||||||
UpdateStrategy: persistentvolume.Strategy,
|
UpdateStrategy: persistentvolume.Strategy,
|
||||||
|
@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return persistentvolumeclaim.MatchPersistentVolumeClaim(label, field)
|
return persistentvolumeclaim.MatchPersistentVolumeClaim(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "persistentvolumeclaims",
|
QualifiedResource: api.Resource("persistentvolumeclaims"),
|
||||||
|
|
||||||
CreateStrategy: persistentvolumeclaim.Strategy,
|
CreateStrategy: persistentvolumeclaim.Strategy,
|
||||||
UpdateStrategy: persistentvolumeclaim.Strategy,
|
UpdateStrategy: persistentvolumeclaim.Strategy,
|
||||||
|
@ -84,7 +84,7 @@ func NewStorage(
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return pod.MatchPod(label, field)
|
return pod.MatchPod(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "pods",
|
QualifiedResource: api.Resource("pods"),
|
||||||
|
|
||||||
CreateStrategy: pod.Strategy,
|
CreateStrategy: pod.Strategy,
|
||||||
UpdateStrategy: pod.Strategy,
|
UpdateStrategy: pod.Strategy,
|
||||||
@ -178,10 +178,10 @@ func (r *BindingREST) setPodHostAndAnnotations(ctx api.Context, podID, oldMachin
|
|||||||
// assignPod assigns the given pod to the given machine.
|
// assignPod assigns the given pod to the given machine.
|
||||||
func (r *BindingREST) assignPod(ctx api.Context, podID string, machine string, annotations map[string]string) (err error) {
|
func (r *BindingREST) assignPod(ctx api.Context, podID string, machine string, annotations map[string]string) (err error) {
|
||||||
if _, err = r.setPodHostAndAnnotations(ctx, podID, "", machine, annotations); err != nil {
|
if _, err = r.setPodHostAndAnnotations(ctx, podID, "", machine, annotations); err != nil {
|
||||||
err = etcderr.InterpretGetError(err, "pod", podID)
|
err = etcderr.InterpretGetError(err, api.Resource("pods"), podID)
|
||||||
err = etcderr.InterpretUpdateError(err, "pod", podID)
|
err = etcderr.InterpretUpdateError(err, api.Resource("pods"), podID)
|
||||||
if _, ok := err.(*errors.StatusError); !ok {
|
if _, ok := err.(*errors.StatusError); !ok {
|
||||||
err = errors.NewConflict("binding", podID, err)
|
err = errors.NewConflict(api.Resource("pods/binding"), podID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -354,7 +354,7 @@ func TestEtcdCreateBindingNoPod(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("Expected not-found-error but got nothing")
|
t.Fatalf("Expected not-found-error but got nothing")
|
||||||
}
|
}
|
||||||
if !errors.IsNotFound(etcderrors.InterpretGetError(err, "Pod", "foo")) {
|
if !errors.IsNotFound(etcderrors.InterpretGetError(err, api.Resource("pods"), "foo")) {
|
||||||
t.Fatalf("Unexpected error returned: %#v", err)
|
t.Fatalf("Unexpected error returned: %#v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ func TestEtcdCreateBindingNoPod(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("Expected not-found-error but got nothing")
|
t.Fatalf("Expected not-found-error but got nothing")
|
||||||
}
|
}
|
||||||
if !errors.IsNotFound(etcderrors.InterpretGetError(err, "Pod", "foo")) {
|
if !errors.IsNotFound(etcderrors.InterpretGetError(err, api.Resource("pods"), "foo")) {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ func (r *LogREST) Get(ctx api.Context, name string, opts runtime.Object) (runtim
|
|||||||
return nil, fmt.Errorf("invalid options object: %#v", opts)
|
return nil, fmt.Errorf("invalid options object: %#v", opts)
|
||||||
}
|
}
|
||||||
if errs := validation.ValidatePodLogOptions(logOpts); len(errs) > 0 {
|
if errs := validation.ValidatePodLogOptions(logOpts); len(errs) > 0 {
|
||||||
return nil, errors.NewInvalid("podlogs", name, errs)
|
return nil, errors.NewInvalid(api.Kind("PodLogOptions"), name, errs)
|
||||||
}
|
}
|
||||||
location, transport, err := pod.LogLocation(r.Store, r.KubeletConn, ctx, name, logOpts)
|
location, transport, err := pod.LogLocation(r.Store, r.KubeletConn, ctx, name, logOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -63,7 +63,7 @@ func (r *LogREST) Get(ctx api.Context, name string, opts runtime.Object) (runtim
|
|||||||
Transport: transport,
|
Transport: transport,
|
||||||
ContentType: "text/plain",
|
ContentType: "text/plain",
|
||||||
Flush: logOpts.Follow,
|
Flush: logOpts.Follow,
|
||||||
ResponseChecker: genericrest.NewGenericHttpResponseChecker("Pod", name),
|
ResponseChecker: genericrest.NewGenericHttpResponseChecker(api.Resource("pods/log"), name),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return podtemplate.MatchPodTemplate(label, field)
|
return podtemplate.MatchPodTemplate(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "podtemplates",
|
QualifiedResource: api.Resource("podtemplates"),
|
||||||
|
|
||||||
CreateStrategy: podtemplate.Strategy,
|
CreateStrategy: podtemplate.Strategy,
|
||||||
UpdateStrategy: podtemplate.Strategy,
|
UpdateStrategy: podtemplate.Strategy,
|
||||||
|
@ -57,7 +57,7 @@ func (e *EndpointRegistry) GetEndpoints(ctx api.Context, name string) (*api.Endp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, errors.NewNotFound("Endpoints", name)
|
return nil, errors.NewNotFound(api.Resource("endpoints"), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EndpointRegistry) WatchEndpoints(ctx api.Context, options *unversioned.ListOptions) (watch.Interface, error) {
|
func (e *EndpointRegistry) WatchEndpoints(ctx api.Context, options *unversioned.ListOptions) (watch.Interface, error) {
|
||||||
|
@ -95,7 +95,7 @@ func (r *NodeRegistry) GetNode(ctx api.Context, nodeID string) (*api.Node, error
|
|||||||
return &node, nil
|
return &node, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, errors.NewNotFound("node", nodeID)
|
return nil, errors.NewNotFound(api.Resource("nodes"), nodeID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *NodeRegistry) DeleteNode(ctx api.Context, nodeID string) error {
|
func (r *NodeRegistry) DeleteNode(ctx api.Context, nodeID string) error {
|
||||||
|
@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return resourcequota.MatchResourceQuota(label, field)
|
return resourcequota.MatchResourceQuota(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "resourcequotas",
|
QualifiedResource: api.Resource("resourcequotas"),
|
||||||
|
|
||||||
CreateStrategy: resourcequota.Strategy,
|
CreateStrategy: resourcequota.Strategy,
|
||||||
UpdateStrategy: resourcequota.Strategy,
|
UpdateStrategy: resourcequota.Strategy,
|
||||||
|
@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return secret.Matcher(label, field)
|
return secret.Matcher(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "secrets",
|
QualifiedResource: api.Resource("secrets"),
|
||||||
|
|
||||||
CreateStrategy: secret.Strategy,
|
CreateStrategy: secret.Strategy,
|
||||||
UpdateStrategy: secret.Strategy,
|
UpdateStrategy: secret.Strategy,
|
||||||
|
@ -88,7 +88,7 @@ func (s strategy) Export(obj runtime.Object, exact bool) error {
|
|||||||
errs := []*field.Error{
|
errs := []*field.Error{
|
||||||
field.Invalid(field.NewPath("type"), t, "can not export service account secrets"),
|
field.Invalid(field.NewPath("type"), t, "can not export service account secrets"),
|
||||||
}
|
}
|
||||||
return errors.NewInvalid("Secret", t.Name, errs)
|
return errors.NewInvalid(api.Kind("Secret"), t.Name, errs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
k8serr "k8s.io/kubernetes/pkg/api/errors"
|
k8serr "k8s.io/kubernetes/pkg/api/errors"
|
||||||
etcderr "k8s.io/kubernetes/pkg/api/errors/etcd"
|
etcderr "k8s.io/kubernetes/pkg/api/errors/etcd"
|
||||||
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/registry/service"
|
"k8s.io/kubernetes/pkg/registry/service"
|
||||||
"k8s.io/kubernetes/pkg/registry/service/allocator"
|
"k8s.io/kubernetes/pkg/registry/service/allocator"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
@ -47,8 +48,8 @@ type Etcd struct {
|
|||||||
storage storage.Interface
|
storage storage.Interface
|
||||||
last string
|
last string
|
||||||
|
|
||||||
baseKey string
|
baseKey string
|
||||||
kind string
|
resource unversioned.GroupResource
|
||||||
}
|
}
|
||||||
|
|
||||||
// Etcd implements allocator.Interface and service.RangeRegistry
|
// Etcd implements allocator.Interface and service.RangeRegistry
|
||||||
@ -57,12 +58,12 @@ var _ service.RangeRegistry = &Etcd{}
|
|||||||
|
|
||||||
// NewEtcd returns an allocator that is backed by Etcd and can manage
|
// NewEtcd returns an allocator that is backed by Etcd and can manage
|
||||||
// persisting the snapshot state of allocation after each allocation is made.
|
// persisting the snapshot state of allocation after each allocation is made.
|
||||||
func NewEtcd(alloc allocator.Snapshottable, baseKey string, kind string, storage storage.Interface) *Etcd {
|
func NewEtcd(alloc allocator.Snapshottable, baseKey string, resource unversioned.GroupResource, storage storage.Interface) *Etcd {
|
||||||
return &Etcd{
|
return &Etcd{
|
||||||
alloc: alloc,
|
alloc: alloc,
|
||||||
storage: storage,
|
storage: storage,
|
||||||
baseKey: baseKey,
|
baseKey: baseKey,
|
||||||
kind: kind,
|
resource: resource,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +147,7 @@ func (e *Etcd) tryUpdate(fn func() error) error {
|
|||||||
storage.SimpleUpdate(func(input runtime.Object) (output runtime.Object, err error) {
|
storage.SimpleUpdate(func(input runtime.Object) (output runtime.Object, err error) {
|
||||||
existing := input.(*api.RangeAllocation)
|
existing := input.(*api.RangeAllocation)
|
||||||
if len(existing.ResourceVersion) == 0 {
|
if len(existing.ResourceVersion) == 0 {
|
||||||
return nil, fmt.Errorf("cannot allocate resources of type %s at this time", e.kind)
|
return nil, fmt.Errorf("cannot allocate resources of type %s at this time", e.resource.String())
|
||||||
}
|
}
|
||||||
if existing.ResourceVersion != e.last {
|
if existing.ResourceVersion != e.last {
|
||||||
if err := e.alloc.Restore(existing.Range, existing.Data); err != nil {
|
if err := e.alloc.Restore(existing.Range, existing.Data); err != nil {
|
||||||
@ -163,7 +164,7 @@ func (e *Etcd) tryUpdate(fn func() error) error {
|
|||||||
return existing, nil
|
return existing, nil
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
return etcderr.InterpretUpdateError(err, e.kind, "")
|
return etcderr.InterpretUpdateError(err, e.resource, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh reloads the RangeAllocation from etcd.
|
// Refresh reloads the RangeAllocation from etcd.
|
||||||
@ -176,7 +177,7 @@ func (e *Etcd) Refresh() (*api.RangeAllocation, error) {
|
|||||||
if storage.IsNotFound(err) {
|
if storage.IsNotFound(err) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return nil, etcderr.InterpretGetError(err, e.kind, "")
|
return nil, etcderr.InterpretGetError(err, e.resource, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
return existing, nil
|
return existing, nil
|
||||||
@ -187,7 +188,7 @@ func (e *Etcd) Refresh() (*api.RangeAllocation, error) {
|
|||||||
func (e *Etcd) Get() (*api.RangeAllocation, error) {
|
func (e *Etcd) Get() (*api.RangeAllocation, error) {
|
||||||
existing := &api.RangeAllocation{}
|
existing := &api.RangeAllocation{}
|
||||||
if err := e.storage.Get(context.TODO(), e.baseKey, existing, true); err != nil {
|
if err := e.storage.Get(context.TODO(), e.baseKey, existing, true); err != nil {
|
||||||
return nil, etcderr.InterpretGetError(err, e.kind, "")
|
return nil, etcderr.InterpretGetError(err, e.resource, "")
|
||||||
}
|
}
|
||||||
return existing, nil
|
return existing, nil
|
||||||
}
|
}
|
||||||
@ -205,17 +206,17 @@ func (e *Etcd) CreateOrUpdate(snapshot *api.RangeAllocation) error {
|
|||||||
switch {
|
switch {
|
||||||
case len(snapshot.ResourceVersion) != 0 && len(existing.ResourceVersion) != 0:
|
case len(snapshot.ResourceVersion) != 0 && len(existing.ResourceVersion) != 0:
|
||||||
if snapshot.ResourceVersion != existing.ResourceVersion {
|
if snapshot.ResourceVersion != existing.ResourceVersion {
|
||||||
return nil, k8serr.NewConflict(e.kind, "", fmt.Errorf("the provided resource version does not match"))
|
return nil, k8serr.NewConflict(e.resource, "", fmt.Errorf("the provided resource version does not match"))
|
||||||
}
|
}
|
||||||
case len(existing.ResourceVersion) != 0:
|
case len(existing.ResourceVersion) != 0:
|
||||||
return nil, k8serr.NewConflict(e.kind, "", fmt.Errorf("another caller has already initialized the resource"))
|
return nil, k8serr.NewConflict(e.resource, "", fmt.Errorf("another caller has already initialized the resource"))
|
||||||
}
|
}
|
||||||
last = snapshot.ResourceVersion
|
last = snapshot.ResourceVersion
|
||||||
return snapshot, nil
|
return snapshot, nil
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return etcderr.InterpretUpdateError(err, e.kind, "")
|
return etcderr.InterpretUpdateError(err, e.resource, "")
|
||||||
}
|
}
|
||||||
err = e.alloc.Restore(snapshot.Range, snapshot.Data)
|
err = e.alloc.Restore(snapshot.Range, snapshot.Data)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -32,7 +32,7 @@ import (
|
|||||||
func newStorage(t *testing.T) (*Etcd, *etcdtesting.EtcdTestServer, allocator.Interface) {
|
func newStorage(t *testing.T) (*Etcd, *etcdtesting.EtcdTestServer, allocator.Interface) {
|
||||||
etcdStorage, server := registrytest.NewEtcdStorage(t, "")
|
etcdStorage, server := registrytest.NewEtcdStorage(t, "")
|
||||||
mem := allocator.NewAllocationMap(100, "rangeSpecValue")
|
mem := allocator.NewAllocationMap(100, "rangeSpecValue")
|
||||||
etcd := NewEtcd(mem, "/ranges/serviceips", "serviceipallocation", etcdStorage)
|
etcd := NewEtcd(mem, "/ranges/serviceips", api.Resource("serviceipallocations"), etcdStorage)
|
||||||
return etcd, server, mem
|
return etcd, server, mem
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ func key() string {
|
|||||||
func TestEmpty(t *testing.T) {
|
func TestEmpty(t *testing.T) {
|
||||||
storage, server, _ := newStorage(t)
|
storage, server, _ := newStorage(t)
|
||||||
defer server.Terminate(t)
|
defer server.Terminate(t)
|
||||||
if _, err := storage.Allocate(1); !strings.Contains(err.Error(), "cannot allocate resources of type serviceipallocation at this time") {
|
if _, err := storage.Allocate(1); !strings.Contains(err.Error(), "cannot allocate resources of type serviceipallocations at this time") {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ func TestStore(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
other = allocator.NewAllocationMap(100, "rangeSpecValue")
|
other = allocator.NewAllocationMap(100, "rangeSpecValue")
|
||||||
otherStorage := NewEtcd(other, "/ranges/serviceips", "serviceipallocation", storage.storage)
|
otherStorage := NewEtcd(other, "/ranges/serviceips", api.Resource("serviceipallocations"), storage.storage)
|
||||||
if ok, err := otherStorage.Allocate(2); ok || err != nil {
|
if ok, err := otherStorage.Allocate(2); ok || err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return service.MatchServices(label, field)
|
return service.MatchServices(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "services",
|
QualifiedResource: api.Resource("services"),
|
||||||
|
|
||||||
CreateStrategy: service.Strategy,
|
CreateStrategy: service.Strategy,
|
||||||
UpdateStrategy: service.Strategy,
|
UpdateStrategy: service.Strategy,
|
||||||
|
@ -44,7 +44,7 @@ func newStorage(t *testing.T) (*etcdtesting.EtcdTestServer, ipallocator.Interfac
|
|||||||
storage := ipallocator.NewAllocatorCIDRRange(cidr, func(max int, rangeSpec string) allocator.Interface {
|
storage := ipallocator.NewAllocatorCIDRRange(cidr, func(max int, rangeSpec string) allocator.Interface {
|
||||||
mem := allocator.NewAllocationMap(max, rangeSpec)
|
mem := allocator.NewAllocationMap(max, rangeSpec)
|
||||||
backing = mem
|
backing = mem
|
||||||
etcd := allocatoretcd.NewEtcd(mem, "/ranges/serviceips", "serviceipallocation", etcdStorage)
|
etcd := allocatoretcd.NewEtcd(mem, "/ranges/serviceips", api.Resource("serviceipallocations"), etcdStorage)
|
||||||
return etcd
|
return etcd
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ func key() string {
|
|||||||
func TestEmpty(t *testing.T) {
|
func TestEmpty(t *testing.T) {
|
||||||
server, storage, _, _ := newStorage(t)
|
server, storage, _, _ := newStorage(t)
|
||||||
defer server.Terminate(t)
|
defer server.Terminate(t)
|
||||||
if err := storage.Allocate(net.ParseIP("192.168.1.2")); !strings.Contains(err.Error(), "cannot allocate resources of type serviceipallocation at this time") {
|
if err := storage.Allocate(net.ParseIP("192.168.1.2")); !strings.Contains(err.Error(), "cannot allocate resources of type serviceipallocations at this time") {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err
|
|||||||
if err := rs.serviceIPs.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil {
|
if err := rs.serviceIPs.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil {
|
||||||
// TODO: when validation becomes versioned, this gets more complicated.
|
// TODO: when validation becomes versioned, this gets more complicated.
|
||||||
el := field.ErrorList{field.Invalid(field.NewPath("spec", "clusterIP"), service.Spec.ClusterIP, err.Error())}
|
el := field.ErrorList{field.Invalid(field.NewPath("spec", "clusterIP"), service.Spec.ClusterIP, err.Error())}
|
||||||
return nil, errors.NewInvalid("Service", service.Name, el)
|
return nil, errors.NewInvalid(api.Kind("Service"), service.Name, el)
|
||||||
}
|
}
|
||||||
releaseServiceIP = true
|
releaseServiceIP = true
|
||||||
}
|
}
|
||||||
@ -109,7 +109,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: when validation becomes versioned, this gets more complicated.
|
// TODO: when validation becomes versioned, this gets more complicated.
|
||||||
el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), servicePort.NodePort, err.Error())}
|
el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), servicePort.NodePort, err.Error())}
|
||||||
return nil, errors.NewInvalid("Service", service.Name, el)
|
return nil, errors.NewInvalid(api.Kind("Service"), service.Name, el)
|
||||||
}
|
}
|
||||||
} else if assignNodePorts {
|
} else if assignNodePorts {
|
||||||
nodePort, err := nodePortOp.AllocateNext()
|
nodePort, err := nodePortOp.AllocateNext()
|
||||||
@ -199,7 +199,7 @@ func (*REST) NewList() runtime.Object {
|
|||||||
func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
|
func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
|
||||||
service := obj.(*api.Service)
|
service := obj.(*api.Service)
|
||||||
if !api.ValidNamespace(ctx, &service.ObjectMeta) {
|
if !api.ValidNamespace(ctx, &service.ObjectMeta) {
|
||||||
return nil, false, errors.NewConflict("service", service.Namespace, fmt.Errorf("Service.Namespace does not match the provided context"))
|
return nil, false, errors.NewConflict(api.Resource("services"), service.Namespace, fmt.Errorf("Service.Namespace does not match the provided context"))
|
||||||
}
|
}
|
||||||
|
|
||||||
oldService, err := rs.registry.GetService(ctx, service.Name)
|
oldService, err := rs.registry.GetService(ctx, service.Name)
|
||||||
@ -210,7 +210,7 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, boo
|
|||||||
// Copy over non-user fields
|
// Copy over non-user fields
|
||||||
// TODO: make this a merge function
|
// TODO: make this a merge function
|
||||||
if errs := validation.ValidateServiceUpdate(service, oldService); len(errs) > 0 {
|
if errs := validation.ValidateServiceUpdate(service, oldService); len(errs) > 0 {
|
||||||
return nil, false, errors.NewInvalid("service", service.Name, errs)
|
return nil, false, errors.NewInvalid(api.Kind("Service"), service.Name, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
nodePortOp := portallocator.StartOperation(rs.serviceNodePorts)
|
nodePortOp := portallocator.StartOperation(rs.serviceNodePorts)
|
||||||
@ -230,7 +230,7 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, boo
|
|||||||
err := nodePortOp.Allocate(nodePort)
|
err := nodePortOp.Allocate(nodePort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), nodePort, err.Error())}
|
el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), nodePort, err.Error())}
|
||||||
return nil, false, errors.NewInvalid("Service", service.Name, el)
|
return nil, false, errors.NewInvalid(api.Kind("Service"), service.Name, el)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -105,17 +105,17 @@ func TestExportService(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckGeneratedNameError(t *testing.T) {
|
func TestCheckGeneratedNameError(t *testing.T) {
|
||||||
expect := errors.NewNotFound("foo", "bar")
|
expect := errors.NewNotFound(api.Resource("foos"), "bar")
|
||||||
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{}); err != expect {
|
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{}); err != expect {
|
||||||
t.Errorf("NotFoundError should be ignored: %v", err)
|
t.Errorf("NotFoundError should be ignored: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expect = errors.NewAlreadyExists("foo", "bar")
|
expect = errors.NewAlreadyExists(api.Resource("foos"), "bar")
|
||||||
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{}); err != expect {
|
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{}); err != expect {
|
||||||
t.Errorf("AlreadyExists should be returned when no GenerateName field: %v", err)
|
t.Errorf("AlreadyExists should be returned when no GenerateName field: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expect = errors.NewAlreadyExists("foo", "bar")
|
expect = errors.NewAlreadyExists(api.Resource("foos"), "bar")
|
||||||
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{ObjectMeta: api.ObjectMeta{GenerateName: "foo"}}); err == nil || !errors.IsServerTimeout(err) {
|
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{ObjectMeta: api.ObjectMeta{GenerateName: "foo"}}); err == nil || !errors.IsServerTimeout(err) {
|
||||||
t.Errorf("expected try again later error: %v", err)
|
t.Errorf("expected try again later error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return serviceaccount.Matcher(label, field)
|
return serviceaccount.Matcher(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "serviceaccounts",
|
QualifiedResource: api.Resource("serviceaccounts"),
|
||||||
|
|
||||||
CreateStrategy: serviceaccount.Strategy,
|
CreateStrategy: serviceaccount.Strategy,
|
||||||
UpdateStrategy: serviceaccount.Strategy,
|
UpdateStrategy: serviceaccount.Strategy,
|
||||||
|
@ -55,9 +55,9 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return thirdpartyresource.Matcher(label, field)
|
return thirdpartyresource.Matcher(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "thirdPartyResources",
|
QualifiedResource: extensions.Resource("thirdpartyresources"),
|
||||||
CreateStrategy: thirdpartyresource.Strategy,
|
CreateStrategy: thirdpartyresource.Strategy,
|
||||||
UpdateStrategy: thirdpartyresource.Strategy,
|
UpdateStrategy: thirdpartyresource.Strategy,
|
||||||
|
|
||||||
Storage: storageInterface,
|
Storage: storageInterface,
|
||||||
}
|
}
|
||||||
|
@ -57,9 +57,9 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator, gro
|
|||||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
return thirdpartyresourcedata.Matcher(label, field)
|
return thirdpartyresourcedata.Matcher(label, field)
|
||||||
},
|
},
|
||||||
EndpointName: "thirdpartyresourcedata",
|
QualifiedResource: extensions.Resource("thirdpartyresourcedatas"),
|
||||||
CreateStrategy: thirdpartyresourcedata.Strategy,
|
CreateStrategy: thirdpartyresourcedata.Strategy,
|
||||||
UpdateStrategy: thirdpartyresourcedata.Strategy,
|
UpdateStrategy: thirdpartyresourcedata.Strategy,
|
||||||
|
|
||||||
Storage: storageInterface,
|
Storage: storageInterface,
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
"k8s.io/kubernetes/pkg/api/meta"
|
"k8s.io/kubernetes/pkg/api/meta"
|
||||||
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/api/validation"
|
"k8s.io/kubernetes/pkg/api/validation"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||||
@ -47,7 +48,7 @@ func ParseWatchResourceVersion(resourceVersion string) (uint64, error) {
|
|||||||
}
|
}
|
||||||
version, err := strconv.ParseUint(resourceVersion, 10, 64)
|
version, err := strconv.ParseUint(resourceVersion, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.NewInvalid("", "", field.ErrorList{
|
return 0, errors.NewInvalid(unversioned.GroupKind{}, "", field.ErrorList{
|
||||||
// Validation errors are supposed to return version-specific field
|
// Validation errors are supposed to return version-specific field
|
||||||
// paths, but this is probably close enough.
|
// paths, but this is probably close enough.
|
||||||
field.Invalid(field.NewPath("resourceVersion"), resourceVersion, err.Error()),
|
field.Invalid(field.NewPath("resourceVersion"), resourceVersion, err.Error()),
|
||||||
|
@ -109,7 +109,7 @@ func TestAdmissionNamespaceExistsUnknownToHandler(t *testing.T) {
|
|||||||
namespace := "test"
|
namespace := "test"
|
||||||
mockClient := &testclient.Fake{}
|
mockClient := &testclient.Fake{}
|
||||||
mockClient.AddReactor("create", "namespaces", func(action testclient.Action) (bool, runtime.Object, error) {
|
mockClient.AddReactor("create", "namespaces", func(action testclient.Action) (bool, runtime.Object, error) {
|
||||||
return true, nil, errors.NewAlreadyExists("namespaces", namespace)
|
return true, nil, errors.NewAlreadyExists(api.Resource("namespaces"), namespace)
|
||||||
})
|
})
|
||||||
|
|
||||||
store := cache.NewStore(cache.MetaNamespaceKeyFunc)
|
store := cache.NewStore(cache.MetaNamespaceKeyFunc)
|
||||||
|
@ -50,7 +50,7 @@ type lifecycle struct {
|
|||||||
func (l *lifecycle) Admit(a admission.Attributes) (err error) {
|
func (l *lifecycle) Admit(a admission.Attributes) (err error) {
|
||||||
// prevent deletion of immortal namespaces
|
// prevent deletion of immortal namespaces
|
||||||
if a.GetOperation() == admission.Delete && a.GetKind() == api.Kind("Namespace") && l.immortalNamespaces.Has(a.GetName()) {
|
if a.GetOperation() == admission.Delete && a.GetKind() == api.Kind("Namespace") && l.immortalNamespaces.Has(a.GetName()) {
|
||||||
return errors.NewForbidden(a.GetKind().Kind, a.GetName(), fmt.Errorf("this namespace may not be deleted"))
|
return errors.NewForbidden(a.GetResource(), a.GetName(), fmt.Errorf("this namespace may not be deleted"))
|
||||||
}
|
}
|
||||||
|
|
||||||
kind, err := api.RESTMapper.KindFor(a.GetResource().WithVersion(""))
|
kind, err := api.RESTMapper.KindFor(a.GetResource().WithVersion(""))
|
||||||
|
@ -58,28 +58,28 @@ func (p *plugin) Admit(a admission.Attributes) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SupplementalGroups != nil {
|
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SupplementalGroups != nil {
|
||||||
return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("SecurityContext.SupplementalGroups is forbidden"))
|
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("SecurityContext.SupplementalGroups is forbidden"))
|
||||||
}
|
}
|
||||||
if pod.Spec.SecurityContext != nil {
|
if pod.Spec.SecurityContext != nil {
|
||||||
if pod.Spec.SecurityContext.SELinuxOptions != nil {
|
if pod.Spec.SecurityContext.SELinuxOptions != nil {
|
||||||
return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("pod.Spec.SecurityContext.SELinuxOptions is forbidden"))
|
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("pod.Spec.SecurityContext.SELinuxOptions is forbidden"))
|
||||||
}
|
}
|
||||||
if pod.Spec.SecurityContext.RunAsUser != nil {
|
if pod.Spec.SecurityContext.RunAsUser != nil {
|
||||||
return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("pod.Spec.SecurityContext.RunAsUser is forbidden"))
|
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("pod.Spec.SecurityContext.RunAsUser is forbidden"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.FSGroup != nil {
|
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.FSGroup != nil {
|
||||||
return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("SecurityContext.FSGroup is forbidden"))
|
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("SecurityContext.FSGroup is forbidden"))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range pod.Spec.Containers {
|
for _, v := range pod.Spec.Containers {
|
||||||
if v.SecurityContext != nil {
|
if v.SecurityContext != nil {
|
||||||
if v.SecurityContext.SELinuxOptions != nil {
|
if v.SecurityContext.SELinuxOptions != nil {
|
||||||
return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("SecurityContext.SELinuxOptions is forbidden"))
|
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("SecurityContext.SELinuxOptions is forbidden"))
|
||||||
}
|
}
|
||||||
if v.SecurityContext.RunAsUser != nil {
|
if v.SecurityContext.RunAsUser != nil {
|
||||||
return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("SecurityContext.RunAsUser is forbidden"))
|
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("SecurityContext.RunAsUser is forbidden"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user