mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-15 14:26:57 +00:00
Updated documentation and adjusted field names
This commit is contained in:
@@ -198,15 +198,15 @@ func NewMethodNotSupported(kind, action string) error {
|
||||
|
||||
// NewServerTimeout returns an error indicating the requested action could not be completed due to a
|
||||
// transient error, and the client should try again.
|
||||
func NewServerTimeout(kind, operation string, retryAfter int) error {
|
||||
func NewServerTimeout(kind, operation string, retryAfterSeconds int) error {
|
||||
return &StatusError{api.Status{
|
||||
Status: api.StatusFailure,
|
||||
Code: http.StatusInternalServerError,
|
||||
Reason: api.StatusReasonServerTimeout,
|
||||
Details: &api.StatusDetails{
|
||||
Kind: kind,
|
||||
ID: operation,
|
||||
RetryAfter: retryAfter,
|
||||
Kind: kind,
|
||||
ID: operation,
|
||||
RetryAfterSeconds: retryAfterSeconds,
|
||||
},
|
||||
Message: fmt.Sprintf("The %s operation against %s could not be completed at this time, please try again.", operation, kind),
|
||||
}}
|
||||
@@ -227,14 +227,14 @@ func NewInternalError(err error) error {
|
||||
|
||||
// NewTimeoutError returns an error indicating that a timeout occurred before the request
|
||||
// could be completed. Clients may retry, but the operation may still complete.
|
||||
func NewTimeoutError(message string, retryAfter int) error {
|
||||
func NewTimeoutError(message string, retryAfterSeconds int) error {
|
||||
return &StatusError{api.Status{
|
||||
Status: api.StatusFailure,
|
||||
Code: StatusServerTimeout,
|
||||
Reason: api.StatusReasonTimeout,
|
||||
Message: fmt.Sprintf("Timeout: %s", message),
|
||||
Details: &api.StatusDetails{
|
||||
RetryAfter: retryAfter,
|
||||
RetryAfterSeconds: retryAfterSeconds,
|
||||
},
|
||||
}}
|
||||
}
|
||||
@@ -308,7 +308,7 @@ func SuggestsClientDelay(err error) (int, bool) {
|
||||
if t.Status().Details != nil {
|
||||
switch t.Status().Reason {
|
||||
case api.StatusReasonServerTimeout, api.StatusReasonTimeout:
|
||||
return t.Status().Details.RetryAfter, true
|
||||
return t.Status().Details.RetryAfterSeconds, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1201,7 +1201,7 @@ type StatusDetails struct {
|
||||
// failure. Not all StatusReasons may provide detailed causes.
|
||||
Causes []StatusCause `json:"causes,omitempty"`
|
||||
// If specified, the time in seconds before the operation should be retried.
|
||||
RetryAfter int `json:"retryAfter,omitempty"`
|
||||
RetryAfterSeconds int `json:"retryAfterSeconds,omitempty"`
|
||||
}
|
||||
|
||||
// Values of Status.Status
|
||||
@@ -1285,7 +1285,7 @@ const (
|
||||
// Details (optional):
|
||||
// "kind" string - the kind attribute of the resource being acted on.
|
||||
// "id" string - the operation that is being attempted.
|
||||
// "retryAfter" int - the number of seconds before the operation should be retried
|
||||
// "retryAfterSeconds" int - the number of seconds before the operation should be retried
|
||||
// Status code 500
|
||||
StatusReasonServerTimeout StatusReason = "ServerTimeout"
|
||||
|
||||
@@ -1293,9 +1293,9 @@ const (
|
||||
// Clients can get this response only when they specified a timeout param in the request,
|
||||
// or if the server cannot complete the operation within a reasonable amount of time.
|
||||
// The request might succeed with an increased value of timeout param. The client *should*
|
||||
// wait at least the number of seconds specified by the retryAfter field.
|
||||
// wait at least the number of seconds specified by the retryAfterSeconds field.
|
||||
// Details (optional):
|
||||
// "retryAfter" int - the number of seconds before the operation should be retried
|
||||
// "retryAfterSeconds" int - the number of seconds before the operation should be retried
|
||||
// Status code 504
|
||||
StatusReasonTimeout StatusReason = "Timeout"
|
||||
|
||||
|
||||
@@ -1015,7 +1015,7 @@ type StatusDetails struct {
|
||||
// failure. Not all StatusReasons may provide detailed causes.
|
||||
Causes []StatusCause `json:"causes,omitempty" description:"the Causes array includes more details associated with the StatusReason failure; not all StatusReasons may provide detailed causes"`
|
||||
// If specified, the time in seconds before the operation should be retried.
|
||||
RetryAfter int `json:"retryAfter,omitempty" description:"the number of seconds before the client should attempt to retry this operation"`
|
||||
RetryAfterSeconds int `json:"retryAfterSeconds,omitempty" description:"the number of seconds before the client should attempt to retry this operation"`
|
||||
}
|
||||
|
||||
// Values of Status.Status
|
||||
|
||||
@@ -1029,7 +1029,7 @@ type StatusDetails struct {
|
||||
// failure. Not all StatusReasons may provide detailed causes.
|
||||
Causes []StatusCause `json:"causes,omitempty" description:"the Causes array includes more details associated with the StatusReason failure; not all StatusReasons may provide detailed causes"`
|
||||
// If specified, the time in seconds before the operation should be retried.
|
||||
RetryAfter int `json:"retryAfter,omitempty" description:"the number of seconds before the client should attempt to retry this operation"`
|
||||
RetryAfterSeconds int `json:"retryAfterSeconds,omitempty" description:"the number of seconds before the client should attempt to retry this operation"`
|
||||
}
|
||||
|
||||
// Values of Status.Status
|
||||
|
||||
@@ -1188,7 +1188,7 @@ type StatusDetails struct {
|
||||
// failure. Not all StatusReasons may provide detailed causes.
|
||||
Causes []StatusCause `json:"causes,omitempty" description:"the Causes array includes more details associated with the StatusReason failure; not all StatusReasons may provide detailed causes"`
|
||||
// If specified, the time in seconds before the operation should be retried.
|
||||
RetryAfter int `json:"retryAfter,omitempty" description:"the number of seconds before the client should attempt to retry this operation"`
|
||||
RetryAfterSeconds int `json:"retryAfterSeconds,omitempty" description:"the number of seconds before the client should attempt to retry this operation"`
|
||||
}
|
||||
|
||||
// Values of Status.Status
|
||||
|
||||
@@ -645,6 +645,24 @@ func (r *Request) transformResponse(resp *http.Response, req *http.Request, body
|
||||
}
|
||||
|
||||
// transformUnstructuredResponseError handles an error from the server that is not in a structured form.
|
||||
// It is expected to transform any response that is not recognizable as a clear server sent error from the
|
||||
// K8S API using the information provided with the request. In practice, HTTP proxies and client libraries
|
||||
// introduce a level of uncertainty to the responses returned by servers that in common use result in
|
||||
// unexpected responses. The rough structure is:
|
||||
//
|
||||
// 1. Assume the server sends you something sane - JSON + well defined error objects + proper codes
|
||||
// - this is the happy path
|
||||
// - when you get this output, trust what the server sends
|
||||
// 2. Guard against empty fields / bodies in received JSON and attempt to cull sufficient info from them to
|
||||
// generate a reasonable facsimile of the original failure.
|
||||
// - Be sure to use a distinct error type or flag that allows a client to distinguish between this and error 1 above
|
||||
// 3. Handle true disconnect failures / completely malformed data by moving up to a more generic client error
|
||||
// 4. Distinguish between various connection failures like SSL certificates, timeouts, proxy errors, unexpected
|
||||
// initial contact, the presence of mismatched body contents from posted content types
|
||||
// - Give these a separate distinct error type and capture as much as possible of the original message
|
||||
//
|
||||
// TODO: introduce further levels of refinement that allow a client to distinguish between 1 and 2-3.
|
||||
// TODO: introduce transformation of generic http.Client.Do() errors that separates 4.
|
||||
func (r *Request) transformUnstructuredResponseError(resp *http.Response, req *http.Request, body []byte) error {
|
||||
if body == nil && resp.Body != nil {
|
||||
if data, err := ioutil.ReadAll(resp.Body); err == nil {
|
||||
@@ -679,11 +697,11 @@ func (r *Request) transformUnstructuredResponseError(resp *http.Response, req *h
|
||||
case errors.StatusUnprocessableEntity:
|
||||
err = errors.NewInvalid(r.resource, r.resourceName, nil)
|
||||
case errors.StatusServerTimeout:
|
||||
retryAfter, _ := retryAfter(resp)
|
||||
err = errors.NewServerTimeout(r.resource, r.verb, retryAfter)
|
||||
retryAfterSeconds, _ := retryAfterSeconds(resp)
|
||||
err = errors.NewServerTimeout(r.resource, r.verb, retryAfterSeconds)
|
||||
case errors.StatusTooManyRequests:
|
||||
retryAfter, _ := retryAfter(resp)
|
||||
err = errors.NewServerTimeout(r.resource, r.verb, retryAfter)
|
||||
retryAfterSeconds, _ := retryAfterSeconds(resp)
|
||||
err = errors.NewServerTimeout(r.resource, r.verb, retryAfterSeconds)
|
||||
case http.StatusInternalServerError:
|
||||
err = errors.NewInternalError(fmt.Errorf(message))
|
||||
}
|
||||
@@ -703,9 +721,9 @@ func isTextResponse(resp *http.Response) bool {
|
||||
return strings.HasPrefix(media, "text/")
|
||||
}
|
||||
|
||||
// retryAfter returns the value of the Retry-After header and true, or 0 and false if
|
||||
// retryAfterSeconds returns the value of the Retry-After header and true, or 0 and false if
|
||||
// the header was missing or not a valid number.
|
||||
func retryAfter(resp *http.Response) (int, bool) {
|
||||
func retryAfterSeconds(resp *http.Response) (int, bool) {
|
||||
if h := resp.Header.Get("Retry-After"); len(h) > 0 {
|
||||
if i, err := strconv.Atoi(h); err == nil {
|
||||
return i, true
|
||||
|
||||
Reference in New Issue
Block a user