Check if response has unformatted error details#4674
Check if response has unformatted error details#4674cpuguy83 wants to merge 3 commits intocontainerd:mainfrom
Conversation
|
Ping @thaJeztah @tonistiigi WDYT? |
e71df13 to
3880fa9
Compare
|
Build succeeded.
|
|
Looks like there is some string matching in |
|
It like the error handling is just incorrect anyway. The specific case of 429 returns an object rather than an array: |
|
But handling the case of this possibly being just an unencoded message is probably OK as well, e.g. maybe the registry is in a degraded state. |
|
What I'm confused about is that it was "fixed" in #3109 (I'm pretty sure @bainsy88 confirmed at the time that the full error message was getting passed through after that PR), and shouldn't have been broken by #3173, at least on its face, since it is still trying to decode into the same value, but with the more canonical approach of letting the decoder read the stream rather than the "ReadAll(..)". |
|
Is it because the registry in this case returns |
|
Oh, I see Brian's point--the response is not an array, so it's not going to decode into |
|
We could update |
`Errors` here should used lowercase `errors` in the json. This should fix issues where error details are not present when the registry returns a non-OK response. Signed-off-by: Brian Goff <[email protected]>
1. See if only a single error is returned if there were no errors in the errors list. 2. Fallback to legacy message type from https://github.com/docker/distribution/blob/749f6afb4572201e3c37325d0ffedb6f32be8950/registry/client/errors.go#L48-L52 Signed-off-by: Brian Goff <[email protected]>
Makes suere we do the same thing in either case and do our best to get an error. Also adds an additional fallback for plain text error responses. Signed-off-by: Brian Goff <[email protected]>
3880fa9 to
a8dd01d
Compare
|
Ok, updated this with some commits split up.
|
|
|
Build succeeded.
|
|
curious; where is the |
|
It's from the errcode being 0, since the server is not giving us one in the json. |
|
LGTM but I'll let @dmcgowan do the final check since he knows this better than I do. |
| continue | ||
| } | ||
| return "", ocispec.Descriptor{}, errors.Errorf("unexpected status code %v: %v", u, resp.Status) | ||
| return "", ocispec.Descriptor{}, getResponseErr(ctx, req, resp) |
There was a problem hiding this comment.
There is a resp.Body.Close() a few lines above this
|
Should we decide wether or not we must support the invalid JSON response? |
|
i.e.; I agree that plain text responses should be returned; mostly wondering where the "backward compat" part in moby / distribution came from, and if it's still relevant (not taking the current Docker Hub response into account) #4672 (comment) |
| if err2 != nil { | ||
| log.G(ctx).WithError(err2).Debug("Error copying response body details") | ||
| } | ||
| return errors.Errorf("unexpected status code %v: %v, details: %s", req.String(), resp.Status, sb) |
There was a problem hiding this comment.
I would rather us type this error, shoveling the raw http body into an error string still doesn't seem right. The cases this occurs is if the registry is not implementing the same error handling format or the response is from middleware. The output is more likely to be mangled html than a valid error message.
We could wrap the registry error type in a response error which holds the request, status code, registry error type. In this case, we can use the unknown registry error type and let the caller decide if it wants to present details.
There was a problem hiding this comment.
The output is more likely to be mangled html than a valid error message.
Distribution spec is a bit sketchy on that ("If the response body is in JSON format"); i.e. it mentions the body to be JSON format, but doesn't mention wether or not that requires the content-type to be application/json (i.e., should a text/plain response be attempted to parse as JSON?)
We could wrap the registry error type in a response error which holds the request, status code, registry error type. In this case, we can use the unknown registry error type and let the caller decide if it wants to present details.
You mean; preserve the body, but convert it to a "valid" format? I think that would work; at least the information would not be lost, and clients should be able to handle the standard format (how to handle other formats is somewhat "unspecified": "A 4XX response code from the registry MAY return a body in any format" )
There was a problem hiding this comment.
@dmcgowan That's a fair point. It also kinda sucks to expect all callers to be aware of this to make that determination.
I'd be fine dropping that, or possibly checking explicitly text/plain as the content type.
There was a problem hiding this comment.
Can you just dump the body into the log and mention the status code is unexpected and the error is not formatted.
|
quick search in the docker/distribution repository; distribution/distribution@ec636bb distribution/distribution#1379
fixes / related to distribution/distribution#1373 |
|
this PR now has conflicts with |
|
There is still a tracking issue, going to close this for now. We do need to address better remote error response handling still. |
In some cases a registry may not return a formaatted message, in this
case try to get error details from the response body as a simple string.
Closes #4672