diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 23cf9e0f52f..02b632f57de 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -61376,7 +61376,7 @@ "type": "string" }, "retryAfterSeconds": { - "description": "If specified, the time in seconds before the operation should be retried.", + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.", "type": "integer", "format": "int32" }, diff --git a/api/swagger-spec/admissionregistration.k8s.io_v1alpha1.json b/api/swagger-spec/admissionregistration.k8s.io_v1alpha1.json index 728467e6158..f6d28b231b0 100644 --- a/api/swagger-spec/admissionregistration.k8s.io_v1alpha1.json +++ b/api/swagger-spec/admissionregistration.k8s.io_v1alpha1.json @@ -1546,7 +1546,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/apps_v1beta1.json b/api/swagger-spec/apps_v1beta1.json index 3d19866302d..5524e1f712d 100644 --- a/api/swagger-spec/apps_v1beta1.json +++ b/api/swagger-spec/apps_v1beta1.json @@ -3460,7 +3460,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/apps_v1beta2.json b/api/swagger-spec/apps_v1beta2.json index 0977ae02c09..dec3f47f914 100644 --- a/api/swagger-spec/apps_v1beta2.json +++ b/api/swagger-spec/apps_v1beta2.json @@ -4812,7 +4812,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/authentication.k8s.io_v1.json b/api/swagger-spec/authentication.k8s.io_v1.json index 2cf3b808f12..ee9a1527afc 100644 --- a/api/swagger-spec/authentication.k8s.io_v1.json +++ b/api/swagger-spec/authentication.k8s.io_v1.json @@ -336,7 +336,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/authentication.k8s.io_v1beta1.json b/api/swagger-spec/authentication.k8s.io_v1beta1.json index fbc0e8b0313..5dfe2af2d9c 100644 --- a/api/swagger-spec/authentication.k8s.io_v1beta1.json +++ b/api/swagger-spec/authentication.k8s.io_v1beta1.json @@ -336,7 +336,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/authorization.k8s.io_v1.json b/api/swagger-spec/authorization.k8s.io_v1.json index e152b05ecb1..e5c42d1eede 100644 --- a/api/swagger-spec/authorization.k8s.io_v1.json +++ b/api/swagger-spec/authorization.k8s.io_v1.json @@ -434,7 +434,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/authorization.k8s.io_v1beta1.json b/api/swagger-spec/authorization.k8s.io_v1beta1.json index 1dad0a04770..915a081db69 100644 --- a/api/swagger-spec/authorization.k8s.io_v1beta1.json +++ b/api/swagger-spec/authorization.k8s.io_v1beta1.json @@ -434,7 +434,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/autoscaling_v1.json b/api/swagger-spec/autoscaling_v1.json index d4ec040026e..58c6b78d36f 100644 --- a/api/swagger-spec/autoscaling_v1.json +++ b/api/swagger-spec/autoscaling_v1.json @@ -1343,7 +1343,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/autoscaling_v2alpha1.json b/api/swagger-spec/autoscaling_v2alpha1.json index 3c84e006708..032683bad37 100644 --- a/api/swagger-spec/autoscaling_v2alpha1.json +++ b/api/swagger-spec/autoscaling_v2alpha1.json @@ -1343,7 +1343,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/batch_v1.json b/api/swagger-spec/batch_v1.json index 9e14a0ac33e..33efe7cb224 100644 --- a/api/swagger-spec/batch_v1.json +++ b/api/swagger-spec/batch_v1.json @@ -1343,7 +1343,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/batch_v2alpha1.json b/api/swagger-spec/batch_v2alpha1.json index 88c183d4ee8..3a9c6a88db8 100644 --- a/api/swagger-spec/batch_v2alpha1.json +++ b/api/swagger-spec/batch_v2alpha1.json @@ -2369,7 +2369,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/certificates.k8s.io_v1beta1.json b/api/swagger-spec/certificates.k8s.io_v1beta1.json index 36d0fc508b7..99d663d81a7 100644 --- a/api/swagger-spec/certificates.k8s.io_v1beta1.json +++ b/api/swagger-spec/certificates.k8s.io_v1beta1.json @@ -1034,7 +1034,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/extensions_v1beta1.json b/api/swagger-spec/extensions_v1beta1.json index 504cf1da6aa..2c74fe32ae9 100644 --- a/api/swagger-spec/extensions_v1beta1.json +++ b/api/swagger-spec/extensions_v1beta1.json @@ -6453,7 +6453,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/networking.k8s.io_v1.json b/api/swagger-spec/networking.k8s.io_v1.json index da0e380b9d3..79a9ac80cb3 100644 --- a/api/swagger-spec/networking.k8s.io_v1.json +++ b/api/swagger-spec/networking.k8s.io_v1.json @@ -1174,7 +1174,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/policy_v1beta1.json b/api/swagger-spec/policy_v1beta1.json index e857130a7d1..10511c69120 100644 --- a/api/swagger-spec/policy_v1beta1.json +++ b/api/swagger-spec/policy_v1beta1.json @@ -1340,7 +1340,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/rbac.authorization.k8s.io_v1alpha1.json b/api/swagger-spec/rbac.authorization.k8s.io_v1alpha1.json index 7166cfd015f..6082897a705 100644 --- a/api/swagger-spec/rbac.authorization.k8s.io_v1alpha1.json +++ b/api/swagger-spec/rbac.authorization.k8s.io_v1alpha1.json @@ -3212,7 +3212,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/rbac.authorization.k8s.io_v1beta1.json b/api/swagger-spec/rbac.authorization.k8s.io_v1beta1.json index 681eb673d1f..7a863a59cb3 100644 --- a/api/swagger-spec/rbac.authorization.k8s.io_v1beta1.json +++ b/api/swagger-spec/rbac.authorization.k8s.io_v1beta1.json @@ -3212,7 +3212,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/scheduling.k8s.io_v1alpha1.json b/api/swagger-spec/scheduling.k8s.io_v1alpha1.json index 66635b1be61..90b531d57ea 100644 --- a/api/swagger-spec/scheduling.k8s.io_v1alpha1.json +++ b/api/swagger-spec/scheduling.k8s.io_v1alpha1.json @@ -940,7 +940,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/settings.k8s.io_v1alpha1.json b/api/swagger-spec/settings.k8s.io_v1alpha1.json index 906485e9ac7..01f1f2ddbbb 100644 --- a/api/swagger-spec/settings.k8s.io_v1alpha1.json +++ b/api/swagger-spec/settings.k8s.io_v1alpha1.json @@ -1172,7 +1172,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/storage.k8s.io_v1.json b/api/swagger-spec/storage.k8s.io_v1.json index 535b1283aee..f86ae454e38 100644 --- a/api/swagger-spec/storage.k8s.io_v1.json +++ b/api/swagger-spec/storage.k8s.io_v1.json @@ -935,7 +935,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/storage.k8s.io_v1beta1.json b/api/swagger-spec/storage.k8s.io_v1beta1.json index a9a8f3f0791..31c31419f2c 100644 --- a/api/swagger-spec/storage.k8s.io_v1beta1.json +++ b/api/swagger-spec/storage.k8s.io_v1beta1.json @@ -935,7 +935,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/api/swagger-spec/v1.json b/api/swagger-spec/v1.json index 84f650630fd..b7ee59b203d 100644 --- a/api/swagger-spec/v1.json +++ b/api/swagger-spec/v1.json @@ -17580,7 +17580,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/docs/api-reference/admissionregistration.k8s.io/v1alpha1/definitions.html b/docs/api-reference/admissionregistration.k8s.io/v1alpha1/definitions.html index 2fbc1a8bc7f..e35dd956901 100755 --- a/docs/api-reference/admissionregistration.k8s.io/v1alpha1/definitions.html +++ b/docs/api-reference/admissionregistration.k8s.io/v1alpha1/definitions.html @@ -1182,7 +1182,7 @@ Depending on the enclosing object, subresources might not be allowed. Required.<

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/apps/v1beta1/definitions.html b/docs/api-reference/apps/v1beta1/definitions.html index 8730ab176a4..e28807b9ddc 100755 --- a/docs/api-reference/apps/v1beta1/definitions.html +++ b/docs/api-reference/apps/v1beta1/definitions.html @@ -5337,7 +5337,7 @@ Examples:

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/apps/v1beta2/definitions.html b/docs/api-reference/apps/v1beta2/definitions.html index abd552247cb..e358e64569d 100755 --- a/docs/api-reference/apps/v1beta2/definitions.html +++ b/docs/api-reference/apps/v1beta2/definitions.html @@ -5588,7 +5588,7 @@ Examples:

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/authentication.k8s.io/v1/definitions.html b/docs/api-reference/authentication.k8s.io/v1/definitions.html index e31e008db4f..2962fcc672b 100755 --- a/docs/api-reference/authentication.k8s.io/v1/definitions.html +++ b/docs/api-reference/authentication.k8s.io/v1/definitions.html @@ -535,7 +535,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/authentication.k8s.io/v1beta1/definitions.html b/docs/api-reference/authentication.k8s.io/v1beta1/definitions.html index 20cf0c87c7f..314dbeac33e 100755 --- a/docs/api-reference/authentication.k8s.io/v1beta1/definitions.html +++ b/docs/api-reference/authentication.k8s.io/v1beta1/definitions.html @@ -624,7 +624,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/authorization.k8s.io/v1/definitions.html b/docs/api-reference/authorization.k8s.io/v1/definitions.html index 97f628970e2..cb8d7366268 100755 --- a/docs/api-reference/authorization.k8s.io/v1/definitions.html +++ b/docs/api-reference/authorization.k8s.io/v1/definitions.html @@ -617,7 +617,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/authorization.k8s.io/v1beta1/definitions.html b/docs/api-reference/authorization.k8s.io/v1beta1/definitions.html index c3c38fabd1b..0bcba126523 100755 --- a/docs/api-reference/authorization.k8s.io/v1beta1/definitions.html +++ b/docs/api-reference/authorization.k8s.io/v1beta1/definitions.html @@ -541,7 +541,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/autoscaling/v1/definitions.html b/docs/api-reference/autoscaling/v1/definitions.html index 5a8a9746248..a6ea7046bb5 100755 --- a/docs/api-reference/autoscaling/v1/definitions.html +++ b/docs/api-reference/autoscaling/v1/definitions.html @@ -668,7 +668,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/autoscaling/v2alpha1/definitions.html b/docs/api-reference/autoscaling/v2alpha1/definitions.html index 70a3f818f37..b649bc388c5 100755 --- a/docs/api-reference/autoscaling/v2alpha1/definitions.html +++ b/docs/api-reference/autoscaling/v2alpha1/definitions.html @@ -1349,7 +1349,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/batch/v1/definitions.html b/docs/api-reference/batch/v1/definitions.html index bd98808b311..41f42054280 100755 --- a/docs/api-reference/batch/v1/definitions.html +++ b/docs/api-reference/batch/v1/definitions.html @@ -4301,7 +4301,7 @@ Examples:

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/batch/v2alpha1/definitions.html b/docs/api-reference/batch/v2alpha1/definitions.html index ca092fe8087..cf7bb70303e 100755 --- a/docs/api-reference/batch/v2alpha1/definitions.html +++ b/docs/api-reference/batch/v2alpha1/definitions.html @@ -4308,7 +4308,7 @@ Examples:

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/certificates.k8s.io/v1beta1/definitions.html b/docs/api-reference/certificates.k8s.io/v1beta1/definitions.html index 2a47cb4534f..c682f7f589b 100755 --- a/docs/api-reference/certificates.k8s.io/v1beta1/definitions.html +++ b/docs/api-reference/certificates.k8s.io/v1beta1/definitions.html @@ -613,7 +613,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/extensions/v1beta1/definitions.html b/docs/api-reference/extensions/v1beta1/definitions.html index c3dec2d21f1..40a6afd78f3 100755 --- a/docs/api-reference/extensions/v1beta1/definitions.html +++ b/docs/api-reference/extensions/v1beta1/definitions.html @@ -6070,7 +6070,7 @@ Both these may change in the future. Incoming requests are matched against the h

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/networking.k8s.io/v1/definitions.html b/docs/api-reference/networking.k8s.io/v1/definitions.html index 955ff174bd9..eec98686c29 100755 --- a/docs/api-reference/networking.k8s.io/v1/definitions.html +++ b/docs/api-reference/networking.k8s.io/v1/definitions.html @@ -658,7 +658,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/policy/v1beta1/definitions.html b/docs/api-reference/policy/v1beta1/definitions.html index 8841ef89a41..c4b3893b531 100755 --- a/docs/api-reference/policy/v1beta1/definitions.html +++ b/docs/api-reference/policy/v1beta1/definitions.html @@ -675,7 +675,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/rbac.authorization.k8s.io/v1alpha1/definitions.html b/docs/api-reference/rbac.authorization.k8s.io/v1alpha1/definitions.html index 319f3ae3f99..935dc706cb8 100755 --- a/docs/api-reference/rbac.authorization.k8s.io/v1alpha1/definitions.html +++ b/docs/api-reference/rbac.authorization.k8s.io/v1alpha1/definitions.html @@ -1065,7 +1065,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/rbac.authorization.k8s.io/v1beta1/definitions.html b/docs/api-reference/rbac.authorization.k8s.io/v1beta1/definitions.html index 31c4fa76915..ef23f83cc15 100755 --- a/docs/api-reference/rbac.authorization.k8s.io/v1beta1/definitions.html +++ b/docs/api-reference/rbac.authorization.k8s.io/v1beta1/definitions.html @@ -803,7 +803,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/scheduling.k8s.io/v1alpha1/definitions.html b/docs/api-reference/scheduling.k8s.io/v1alpha1/definitions.html index c008fd569d1..d22e4c9e5c6 100755 --- a/docs/api-reference/scheduling.k8s.io/v1alpha1/definitions.html +++ b/docs/api-reference/scheduling.k8s.io/v1alpha1/definitions.html @@ -613,7 +613,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html b/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html index 85ab797aab5..9b59e8f261a 100755 --- a/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html +++ b/docs/api-reference/settings.k8s.io/v1alpha1/definitions.html @@ -1543,7 +1543,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/storage.k8s.io/v1/definitions.html b/docs/api-reference/storage.k8s.io/v1/definitions.html index a230d5d93ae..19a38db5df4 100755 --- a/docs/api-reference/storage.k8s.io/v1/definitions.html +++ b/docs/api-reference/storage.k8s.io/v1/definitions.html @@ -613,7 +613,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/storage.k8s.io/v1beta1/definitions.html b/docs/api-reference/storage.k8s.io/v1beta1/definitions.html index f45beab60ca..c55d3b0c6d2 100755 --- a/docs/api-reference/storage.k8s.io/v1beta1/definitions.html +++ b/docs/api-reference/storage.k8s.io/v1beta1/definitions.html @@ -668,7 +668,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/docs/api-reference/v1/definitions.html b/docs/api-reference/v1/definitions.html index 3d3779e8105..9f1866413d2 100755 --- a/docs/api-reference/v1/definitions.html +++ b/docs/api-reference/v1/definitions.html @@ -6979,7 +6979,7 @@ Examples:

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/federation/apis/openapi-spec/swagger.json b/federation/apis/openapi-spec/swagger.json index 9d80b7ac4e6..3348e64685e 100644 --- a/federation/apis/openapi-spec/swagger.json +++ b/federation/apis/openapi-spec/swagger.json @@ -13697,7 +13697,7 @@ "type": "string" }, "retryAfterSeconds": { - "description": "If specified, the time in seconds before the operation should be retried.", + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.", "type": "integer", "format": "int32" }, diff --git a/federation/apis/swagger-spec/extensions_v1beta1.json b/federation/apis/swagger-spec/extensions_v1beta1.json index 5e1c5e1774c..6eac8ab38f1 100644 --- a/federation/apis/swagger-spec/extensions_v1beta1.json +++ b/federation/apis/swagger-spec/extensions_v1beta1.json @@ -4812,7 +4812,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/federation/apis/swagger-spec/federation_v1beta1.json b/federation/apis/swagger-spec/federation_v1beta1.json index 0529718d95b..120831f1f8f 100644 --- a/federation/apis/swagger-spec/federation_v1beta1.json +++ b/federation/apis/swagger-spec/federation_v1beta1.json @@ -985,7 +985,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/federation/apis/swagger-spec/v1.json b/federation/apis/swagger-spec/v1.json index bad86926c0f..ecff7047267 100644 --- a/federation/apis/swagger-spec/v1.json +++ b/federation/apis/swagger-spec/v1.json @@ -4652,7 +4652,7 @@ "retryAfterSeconds": { "type": "integer", "format": "int32", - "description": "If specified, the time in seconds before the operation should be retried." + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." } } }, diff --git a/federation/docs/api-reference/extensions/v1beta1/definitions.html b/federation/docs/api-reference/extensions/v1beta1/definitions.html index c7592ccaa57..371167b51e8 100755 --- a/federation/docs/api-reference/extensions/v1beta1/definitions.html +++ b/federation/docs/api-reference/extensions/v1beta1/definitions.html @@ -5594,7 +5594,7 @@ Both these may change in the future. Incoming requests are matched against the h

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/federation/docs/api-reference/federation/v1beta1/definitions.html b/federation/docs/api-reference/federation/v1beta1/definitions.html index 2d726cbba9d..46ac97d5946 100755 --- a/federation/docs/api-reference/federation/v1beta1/definitions.html +++ b/federation/docs/api-reference/federation/v1beta1/definitions.html @@ -709,7 +709,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/federation/docs/api-reference/v1/definitions.html b/federation/docs/api-reference/v1/definitions.html index eb45dffacdb..155a431941e 100755 --- a/federation/docs/api-reference/v1/definitions.html +++ b/federation/docs/api-reference/v1/definitions.html @@ -1442,7 +1442,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

retryAfterSeconds

-

If specified, the time in seconds before the operation should be retried.

+

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

diff --git a/pkg/kubelet/server/BUILD b/pkg/kubelet/server/BUILD index 94381c2f3c7..901302092a4 100644 --- a/pkg/kubelet/server/BUILD +++ b/pkg/kubelet/server/BUILD @@ -37,7 +37,6 @@ go_library( "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus/promhttp:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", @@ -79,7 +78,6 @@ go_test( "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/golang.org/x/net/websocket:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library", diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go index e728daaf784..74a5036828a 100644 --- a/pkg/kubelet/server/server.go +++ b/pkg/kubelet/server/server.go @@ -39,7 +39,6 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" "k8s.io/api/core/v1" - apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -484,7 +483,7 @@ func (s *Server) getContainerLogs(request *restful.Request, response *restful.Re } logOptions.TypeMeta = metav1.TypeMeta{} if errs := validation.ValidatePodLogOptions(logOptions); len(errs) > 0 { - response.WriteError(apierrs.StatusUnprocessableEntity, fmt.Errorf(`{"message": "Invalid request."}`)) + response.WriteError(http.StatusUnprocessableEntity, fmt.Errorf(`{"message": "Invalid request."}`)) return } diff --git a/pkg/kubelet/server/server_test.go b/pkg/kubelet/server/server_test.go index 015947ddac4..b3b5ce9b46e 100644 --- a/pkg/kubelet/server/server_test.go +++ b/pkg/kubelet/server/server_test.go @@ -39,7 +39,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "k8s.io/api/core/v1" - apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/httpstream" @@ -1065,7 +1064,7 @@ func TestContainerLogsWithInvalidTail(t *testing.T) { t.Errorf("Got error GETing: %v", err) } defer resp.Body.Close() - if resp.StatusCode != apierrs.StatusUnprocessableEntity { + if resp.StatusCode != http.StatusUnprocessableEntity { t.Errorf("Unexpected non-error reading container logs: %#v", resp) } } diff --git a/pkg/registry/core/pod/storage/eviction.go b/pkg/registry/core/pod/storage/eviction.go index 2c2d522bb91..468a25330ef 100644 --- a/pkg/registry/core/pod/storage/eviction.go +++ b/pkg/registry/core/pod/storage/eviction.go @@ -101,24 +101,9 @@ func (r *EvictionREST) Create(ctx genericapirequest.Context, obj runtime.Object, // If it was false already, or if it becomes false during the course of our retries, // raise an error marked as a 429. - ok, err := r.checkAndDecrement(pod.Namespace, pod.Name, pdb) - if err != nil { + if err := r.checkAndDecrement(pod.Namespace, pod.Name, pdb); err != nil { return err } - - if !ok { - rtStatus = &metav1.Status{ - Status: metav1.StatusFailure, - // TODO(mml): Include some more details about why the eviction is disallowed. - // Ideally any such text is generated by the DisruptionController (offline). - Message: "Cannot evict pod as it would violate the pod's disruption budget.", - Code: 429, - // TODO(mml): Add a Retry-After header. Once there are time-based - // budgets, we can sometimes compute a sensible suggested value. But - // even without that, we can give a suggestion (10 minutes?) that - // prevents well-behaved clients from hammering us. - } - } } return nil }) @@ -146,19 +131,28 @@ func (r *EvictionREST) Create(ctx genericapirequest.Context, obj runtime.Object, } // checkAndDecrement checks if the provided PodDisruptionBudget allows any disruption. -func (r *EvictionREST) checkAndDecrement(namespace string, podName string, pdb policy.PodDisruptionBudget) (ok bool, err error) { +func (r *EvictionREST) checkAndDecrement(namespace string, podName string, pdb policy.PodDisruptionBudget) error { if pdb.Status.ObservedGeneration < pdb.Generation { - return false, nil + // TODO(mml): Add a Retry-After header. Once there are time-based + // budgets, we can sometimes compute a sensible suggested value. But + // even without that, we can give a suggestion (10 minutes?) that + // prevents well-behaved clients from hammering us. + err := errors.NewTooManyRequests("Cannot evict pod as it would violate the pod's disruption budget.", 0) + err.ErrStatus.Details.Causes = append(err.ErrStatus.Details.Causes, metav1.StatusCause{Type: "DisruptionBudget", Message: fmt.Sprintf("The disruption budget %s is still being processed by the server.", pdb.Name)}) + return err } if pdb.Status.PodDisruptionsAllowed < 0 { - return false, errors.NewForbidden(policy.Resource("poddisruptionbudget"), pdb.Name, fmt.Errorf("pdb disruptions allowed is negative")) + return errors.NewForbidden(policy.Resource("poddisruptionbudget"), pdb.Name, fmt.Errorf("pdb disruptions allowed is negative")) } if len(pdb.Status.DisruptedPods) > MaxDisruptedPodSize { - return false, errors.NewForbidden(policy.Resource("poddisruptionbudget"), pdb.Name, fmt.Errorf("DisrputedPods map too big - too many evictions not confirmed by PDB controller")) + return errors.NewForbidden(policy.Resource("poddisruptionbudget"), pdb.Name, fmt.Errorf("DisruptedPods map too big - too many evictions not confirmed by PDB controller")) } if pdb.Status.PodDisruptionsAllowed == 0 { - return false, nil + err := errors.NewTooManyRequests("Cannot evict pod as it would violate the pod's disruption budget.", 0) + err.ErrStatus.Details.Causes = append(err.ErrStatus.Details.Causes, metav1.StatusCause{Type: "DisruptionBudget", Message: fmt.Sprintf("The disruption budget %s needs %d healthy pods and has %d currently", pdb.Name, pdb.Status.DesiredHealthy, pdb.Status.CurrentHealthy)}) + return err } + pdb.Status.PodDisruptionsAllowed-- if pdb.Status.DisruptedPods == nil { pdb.Status.DisruptedPods = make(map[string]metav1.Time) @@ -169,10 +163,10 @@ func (r *EvictionREST) checkAndDecrement(namespace string, podName string, pdb p // be deleted at all and remove it from DisruptedPod map. pdb.Status.DisruptedPods[podName] = metav1.Time{Time: time.Now()} if _, err := r.podDisruptionBudgetClient.PodDisruptionBudgets(namespace).UpdateStatus(&pdb); err != nil { - return false, err + return err } - return true, nil + return nil } // getPodDisruptionBudgets returns any PDBs that match the pod or err if there's an error. diff --git a/staging/src/k8s.io/apimachinery/pkg/api/errors/errors.go b/staging/src/k8s.io/apimachinery/pkg/api/errors/errors.go index 560c889b9c1..91975be85b3 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/errors/errors.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/errors/errors.go @@ -28,16 +28,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" ) -// HTTP Status codes not in the golang http package. -const ( - StatusUnprocessableEntity = 422 - StatusTooManyRequests = 429 - // StatusServerTimeout is an indication that a transient server error has - // occurred and the client *should* retry, with an optional Retry-After - // header to specify the back off window. - StatusServerTimeout = 504 -) - // StatusError is an error intended for consumption by a REST API server; it can also be // reconstructed by clients from a REST response. Public to allow easy type switches. type StatusError struct { @@ -189,7 +179,7 @@ func NewInvalid(qualifiedKind schema.GroupKind, name string, errs field.ErrorLis } return &StatusError{metav1.Status{ Status: metav1.StatusFailure, - Code: StatusUnprocessableEntity, // RFC 4918: StatusUnprocessableEntity + Code: http.StatusUnprocessableEntity, Reason: metav1.StatusReasonInvalid, Details: &metav1.StatusDetails{ Group: qualifiedKind.Group, @@ -211,6 +201,21 @@ func NewBadRequest(reason string) *StatusError { }} } +// NewTooManyRequests creates an error that indicates that the client must try again later because +// the specified endpoint is not accepting requests. More specific details should be provided +// if client should know why the failure was limited4. +func NewTooManyRequests(message string, retryAfterSeconds int) *StatusError { + return &StatusError{metav1.Status{ + Status: metav1.StatusFailure, + Code: http.StatusTooManyRequests, + Reason: metav1.StatusReasonTooManyRequests, + Message: message, + Details: &metav1.StatusDetails{ + RetryAfterSeconds: int32(retryAfterSeconds), + }, + }} +} + // NewServiceUnavailable creates an error that indicates that the requested service is unavailable. func NewServiceUnavailable(reason string) *StatusError { return &StatusError{metav1.Status{ @@ -276,7 +281,7 @@ func NewInternalError(err error) *StatusError { func NewTimeoutError(message string, retryAfterSeconds int) *StatusError { return &StatusError{metav1.Status{ Status: metav1.StatusFailure, - Code: StatusServerTimeout, + Code: http.StatusGatewayTimeout, Reason: metav1.StatusReasonTimeout, Message: fmt.Sprintf("Timeout: %s", message), Details: &metav1.StatusDetails{ @@ -313,14 +318,14 @@ func NewGenericServerResponse(code int, verb string, qualifiedResource schema.Gr case http.StatusMethodNotAllowed: reason = metav1.StatusReasonMethodNotAllowed message = "the server does not allow this method on the requested resource" - case StatusUnprocessableEntity: + case http.StatusUnprocessableEntity: reason = metav1.StatusReasonInvalid message = "the server rejected our request due to an error in our request" - case StatusServerTimeout: - reason = metav1.StatusReasonServerTimeout - message = "the server cannot complete the requested operation at this time, try again later" - case StatusTooManyRequests: + case http.StatusGatewayTimeout: reason = metav1.StatusReasonTimeout + message = "the server was unable to return a response in the time allotted, but may still be processing the request" + case http.StatusTooManyRequests: + reason = metav1.StatusReasonTooManyRequests message = "the server has received too many requests and has asked us to try again later" default: if code >= 500 { @@ -423,11 +428,13 @@ func IsInternalError(err error) bool { // IsTooManyRequests determines if err is an error which indicates that there are too many requests // that the server cannot handle. -// TODO: update IsTooManyRequests() when the TooManyRequests(429) error returned from the API server has a non-empty Reason field func IsTooManyRequests(err error) bool { + if reasonForError(err) == metav1.StatusReasonTooManyRequests { + return true + } switch t := err.(type) { case APIStatus: - return t.Status().Code == StatusTooManyRequests + return t.Status().Code == http.StatusTooManyRequests } return false } @@ -455,13 +462,20 @@ func IsUnexpectedObjectError(err error) bool { } // SuggestsClientDelay returns true if this error suggests a client delay as well as the -// suggested seconds to wait, or false if the error does not imply a wait. +// suggested seconds to wait, or false if the error does not imply a wait. It does not +// address whether the error *should* be retried, since some errors (like a 3xx) may +// request delay without retry. func SuggestsClientDelay(err error) (int, bool) { switch t := err.(type) { case APIStatus: if t.Status().Details != nil { switch t.Status().Reason { - case metav1.StatusReasonServerTimeout, metav1.StatusReasonTimeout: + // this StatusReason explicitly requests the caller to delay the action + case metav1.StatusReasonServerTimeout: + return int(t.Status().Details.RetryAfterSeconds), true + } + // If the client requests that we retry after a certain number of seconds + if t.Status().Details.RetryAfterSeconds > 0 { return int(t.Status().Details.RetryAfterSeconds), true } } diff --git a/staging/src/k8s.io/apimachinery/pkg/api/errors/errors_test.go b/staging/src/k8s.io/apimachinery/pkg/api/errors/errors_test.go index ab14e7af9a1..afc26fd31c4 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/errors/errors_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/errors/errors_test.go @@ -83,15 +83,34 @@ func TestErrorNew(t *testing.T) { if !IsServerTimeout(NewServerTimeout(resource("tests"), "reason", 0)) { t.Errorf("expected to be %s", metav1.StatusReasonServerTimeout) } - if time, ok := SuggestsClientDelay(NewServerTimeout(resource("tests"), "doing something", 10)); time != 10 || !ok { - t.Errorf("expected to be %s", metav1.StatusReasonServerTimeout) - } - if time, ok := SuggestsClientDelay(NewTimeoutError("test reason", 10)); time != 10 || !ok { - t.Errorf("expected to be %s", metav1.StatusReasonTimeout) - } if !IsMethodNotSupported(NewMethodNotSupported(resource("foos"), "delete")) { t.Errorf("expected to be %s", metav1.StatusReasonMethodNotAllowed) } + + if time, ok := SuggestsClientDelay(NewServerTimeout(resource("tests"), "doing something", 10)); time != 10 || !ok { + t.Errorf("unexpected %d", time) + } + if time, ok := SuggestsClientDelay(NewServerTimeout(resource("tests"), "doing something", 0)); time != 0 || !ok { + t.Errorf("unexpected %d", time) + } + if time, ok := SuggestsClientDelay(NewTimeoutError("test reason", 10)); time != 10 || !ok { + t.Errorf("unexpected %d", time) + } + if time, ok := SuggestsClientDelay(NewTooManyRequests("doing something", 10)); time != 10 || !ok { + t.Errorf("unexpected %d", time) + } + if time, ok := SuggestsClientDelay(NewTooManyRequests("doing something", 1)); time != 1 || !ok { + t.Errorf("unexpected %d", time) + } + if time, ok := SuggestsClientDelay(NewGenericServerResponse(429, "get", resource("tests"), "test", "doing something", 10, true)); time != 10 || !ok { + t.Errorf("unexpected %d", time) + } + if time, ok := SuggestsClientDelay(NewGenericServerResponse(500, "get", resource("tests"), "test", "doing something", 10, true)); time != 10 || !ok { + t.Errorf("unexpected %d", time) + } + if time, ok := SuggestsClientDelay(NewGenericServerResponse(429, "get", resource("tests"), "test", "doing something", 0, true)); time != 0 || ok { + t.Errorf("unexpected %d", time) + } } func TestNewInvalid(t *testing.T) { diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto index 9355a13092d..1362b4d42cd 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto @@ -678,7 +678,9 @@ message StatusDetails { // +optional repeated StatusCause causes = 4; - // If specified, the time in seconds before the operation should be retried. + // If specified, the time in seconds before the operation should be retried. Some errors may indicate + // the client must take an alternate action - for those errors this field may indicate how long to wait + // before taking the alternate action. // +optional optional int32 retryAfterSeconds = 5; } diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go index 14c7255c92b..2e709b64986 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go @@ -481,7 +481,9 @@ type StatusDetails struct { // failure. Not all StatusReasons may provide detailed causes. // +optional Causes []StatusCause `json:"causes,omitempty" protobuf:"bytes,4,rep,name=causes"` - // If specified, the time in seconds before the operation should be retried. + // If specified, the time in seconds before the operation should be retried. Some errors may indicate + // the client must take an alternate action - for those errors this field may indicate how long to wait + // before taking the alternate action. // +optional RetryAfterSeconds int32 `json:"retryAfterSeconds,omitempty" protobuf:"varint,5,opt,name=retryAfterSeconds"` } @@ -586,6 +588,15 @@ const ( // Status code 504 StatusReasonTimeout StatusReason = "Timeout" + // StatusReasonTooManyRequests means the server experienced too many requests within a + // given window and that the client must wait to perform the action again. A client may + // always retry the request that led to this error, although the client should wait at least + // the number of seconds specified by the retryAfterSeconds field. + // Details (optional): + // "retryAfterSeconds" int32 - the number of seconds before the operation should be retried + // Status code 429 + StatusReasonTooManyRequests StatusReason = "TooManyRequests" + // StatusReasonBadRequest means that the request itself was invalid, because the request // doesn't make any sense, for example deleting a read-only object. This is different than // StatusReasonInvalid above which indicates that the API call could possibly succeed, but the diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go index 159164d7c95..62860a27c6b 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types_swagger_doc_generated.go @@ -295,7 +295,7 @@ var map_StatusDetails = map[string]string{ "kind": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", "uid": "UID of the resource. (when there is a single resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids", "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. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.", } func (StatusDetails) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go index 19980d543d1..361cb56d07b 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/apiserver_test.go @@ -3749,7 +3749,7 @@ func TestCreateTimeout(t *testing.T) { if err != nil { t.Errorf("unexpected error: %v", err) } - itemOut := expectApiStatus(t, "POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo?timeout=4ms", data, apierrs.StatusServerTimeout) + itemOut := expectApiStatus(t, "POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo?timeout=4ms", data, http.StatusGatewayTimeout) if itemOut.Status != metav1.StatusFailure || itemOut.Reason != metav1.StatusReasonTimeout { t.Errorf("Unexpected status %#v", itemOut) } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go index 19515f5bf2c..5802aeb97d9 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go @@ -511,7 +511,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag // http.StatusUnsupportedMediaType, http.StatusNotAcceptable, // http.StatusBadRequest, http.StatusUnauthorized, http.StatusForbidden, // http.StatusRequestTimeout, http.StatusConflict, http.StatusPreconditionFailed, - // 422 (StatusUnprocessableEntity), http.StatusInternalServerError, + // http.StatusUnprocessableEntity, http.StatusInternalServerError, // http.StatusServiceUnavailable // and api error codes // Note that if we specify a versioned Status object here, we may need to diff --git a/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD b/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD index 5eede2d712c..ac14d153d67 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD @@ -46,7 +46,6 @@ go_library( "//vendor/github.com/emicklei/go-restful:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go b/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go index 3e159c21f28..8a1773df7e9 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go @@ -22,7 +22,6 @@ import ( "strings" "time" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/endpoints/metrics" @@ -113,7 +112,11 @@ func WithMaxInFlightLimit( if requestInfo.Namespace != "" { scope = "namespace" } - metrics.MonitorRequest(r, strings.ToUpper(requestInfo.Verb), requestInfo.Resource, requestInfo.Subresource, "", scope, errors.StatusTooManyRequests, 0, time.Now()) + if requestInfo.IsResourceRequest { + metrics.MonitorRequest(r, strings.ToUpper(requestInfo.Verb), requestInfo.Resource, requestInfo.Subresource, "", scope, http.StatusTooManyRequests, 0, time.Now()) + } else { + metrics.MonitorRequest(r, strings.ToUpper(requestInfo.Verb), "", requestInfo.Path, "", scope, http.StatusTooManyRequests, 0, time.Now()) + } tooManyRequests(r, w) } } @@ -123,5 +126,5 @@ func WithMaxInFlightLimit( func tooManyRequests(req *http.Request, w http.ResponseWriter) { // Return a 429 status indicating "Too Many Requests" w.Header().Set("Retry-After", retryAfter) - http.Error(w, "Too many requests, please try again later.", errors.StatusTooManyRequests) + http.Error(w, "Too many requests, please try again later.", http.StatusTooManyRequests) } diff --git a/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight_test.go b/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight_test.go index 79e185e818c..fc302b22b4f 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight_test.go @@ -24,7 +24,6 @@ import ( "sync" "testing" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apiserver/pkg/authentication/user" apifilters "k8s.io/apiserver/pkg/endpoints/filters" @@ -148,7 +147,7 @@ func TestMaxInFlightNonMutating(t *testing.T) { // Do this multiple times to show that rate limit rejected requests don't block. for i := 0; i < 2; i++ { - if err := expectHTTPGet(server.URL, errors.StatusTooManyRequests); err != nil { + if err := expectHTTPGet(server.URL, http.StatusTooManyRequests); err != nil { t.Error(err) } } @@ -213,7 +212,7 @@ func TestMaxInFlightMutating(t *testing.T) { // Do this multiple times to show that rate limit rejected requests don't block. for i := 0; i < 2; i++ { - if err := expectHTTPPost(server.URL+"/foo/bar/", errors.StatusTooManyRequests); err != nil { + if err := expectHTTPPost(server.URL+"/foo/bar/", http.StatusTooManyRequests); err != nil { t.Error(err) } } diff --git a/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go b/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go index e3e21a5f031..1e13f247f03 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go @@ -27,7 +27,6 @@ import ( "time" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/endpoints/metrics" apirequest "k8s.io/apiserver/pkg/endpoints/request" ) @@ -64,9 +63,13 @@ func WithTimeoutForNonLongRunningRequests(handler http.Handler, requestContextMa if requestInfo.Namespace != "" { scope = "namespace" } - metrics.MonitorRequest(req, strings.ToUpper(requestInfo.Verb), requestInfo.Resource, requestInfo.Subresource, "", scope, http.StatusInternalServerError, 0, now) + if requestInfo.IsResourceRequest { + metrics.MonitorRequest(req, strings.ToUpper(requestInfo.Verb), requestInfo.Resource, requestInfo.Subresource, "", scope, http.StatusGatewayTimeout, 0, now) + } else { + metrics.MonitorRequest(req, strings.ToUpper(requestInfo.Verb), "", requestInfo.Path, "", scope, http.StatusGatewayTimeout, 0, now) + } } - return time.After(globalTimeout), metricFn, apierrors.NewServerTimeout(schema.GroupResource{Group: requestInfo.APIGroup, Resource: requestInfo.Resource}, requestInfo.Verb, 0) + return time.After(globalTimeout), metricFn, apierrors.NewTimeoutError(fmt.Sprintf("request did not complete within %s", globalTimeout), 0) } return WithTimeout(handler, timeoutFunc) } @@ -74,7 +77,7 @@ func WithTimeoutForNonLongRunningRequests(handler http.Handler, requestContextMa // WithTimeout returns an http.Handler that runs h with a timeout // determined by timeoutFunc. The new http.Handler calls h.ServeHTTP to handle // each request, but if a call runs for longer than its time limit, the -// handler responds with a 503 Service Unavailable error and the message +// handler responds with a 504 Gateway Timeout error and the message // provided. (If msg is empty, a suitable default message will be sent.) After // the handler times out, writes by h to its http.ResponseWriter will return // http.ErrHandlerTimeout. If timeoutFunc returns a nil timeout channel, no diff --git a/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go b/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go index 4f03b50e74b..b1a897a193a 100755 --- a/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go +++ b/staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go @@ -90,6 +90,11 @@ func WithExponentialBackoff(initialBackoff time.Duration, webhookFn func() error var err error wait.ExponentialBackoff(backoff, func() (bool, error) { err = webhookFn() + // these errors indicate a need to retry an authentication check + if apierrors.IsServerTimeout(err) || apierrors.IsTimeout(err) || apierrors.IsTooManyRequests(err) { + return false, nil + } + // if the error sends the Retry-After header, we respect it as an explicit confirmation we should retry. if _, shouldRetry := apierrors.SuggestsClientDelay(err); shouldRetry { return false, nil } diff --git a/staging/src/k8s.io/client-go/rest/request.go b/staging/src/k8s.io/client-go/rest/request.go index b90984043e6..5e245aeba9e 100644 --- a/staging/src/k8s.io/client-go/rest/request.go +++ b/staging/src/k8s.io/client-go/rest/request.go @@ -889,7 +889,7 @@ func isTextResponse(resp *http.Response) bool { func checkWait(resp *http.Response) (int, bool) { switch r := resp.StatusCode; { // any 500 error code and 429 can trigger a wait - case r == errors.StatusTooManyRequests, r >= 500: + case r == http.StatusTooManyRequests, r >= 500: default: return 0, false } diff --git a/staging/src/k8s.io/client-go/rest/request_test.go b/staging/src/k8s.io/client-go/rest/request_test.go index fa016dfe1ce..0691fc7260c 100755 --- a/staging/src/k8s.io/client-go/rest/request_test.go +++ b/staging/src/k8s.io/client-go/rest/request_test.go @@ -1130,7 +1130,7 @@ func TestCheckRetryClosesBody(t *testing.T) { return } w.Header().Set("Retry-After", "1") - http.Error(w, "Too many requests, please try again later.", apierrors.StatusTooManyRequests) + http.Error(w, "Too many requests, please try again later.", http.StatusTooManyRequests) })) defer testServer.Close() @@ -1204,7 +1204,7 @@ func TestCheckRetryHandles429And5xx(t *testing.T) { return } w.Header().Set("Retry-After", "0") - w.WriteHeader([]int{apierrors.StatusTooManyRequests, 500, 501, 504}[count]) + w.WriteHeader([]int{http.StatusTooManyRequests, 500, 501, 504}[count]) count++ })) defer testServer.Close() @@ -1234,7 +1234,7 @@ func BenchmarkCheckRetryClosesBody(b *testing.B) { return } w.Header().Set("Retry-After", "0") - w.WriteHeader(apierrors.StatusTooManyRequests) + w.WriteHeader(http.StatusTooManyRequests) })) defer testServer.Close()