Pass upstream client's user agent through to registry on image pulls#21306
Conversation
|
Design LGTM |
daemon/daemon.go
Outdated
There was a problem hiding this comment.
I think we should use context.Background() if we're not going to handle the user agent in this case.
|
Thanks! I haven't tested, but from a rapid overview code LGTM (I do think the dependency graph in this PR puts us in a better position to split out the server-side API code out of the repo). 👍 |
There was a problem hiding this comment.
Could this check for the expected client UA? Perhaps with a permissing regexp so the test isn't tied to a particular client version?
|
I probably should have throught of this earlier, but wouldn't it make sense to pass through the client user agent on pushes, searches, and login operations as well? It feels like that would be a lot more consistent. |
|
@aaronlehmann Yes, I want to do this in a future PR. This PR is intended as an incremental step to get to that point. |
|
I understand the desire to make incremental progress, but wouldn't it be awkward for registry operators gathering these statistics if some Engine versions include the client user agent during all operations, and some only do it for pulls? I'd be happy to help make these changes for the other operations if time is an issue. |
|
I have a local branch that extends this to support push, login, and search: aaronlehmann@41f3d16. This also makes some improvements to the integration test. I didn't go through the effort to support it in Let's finalize this PR first (@mgoelzer, I know you're looking to tweak the User-Agent format), and then I can rebase my changes on top of what gets merged and open a separate PR. |
|
I have updated the PR to use the following format (suggested to me by @stevvooe): where To parse it, one would presumably match on ".+ UPSTREAM-CLIENT([^)])", extract the right-hand side substring (stuff between the parens), unescape it and then process as needed. Any feedback on the new format? @aaronlehmann @calavera |
|
docker run, similar to docker build can also trigger pulling images. If we dont plan to distinguish a user-initiated interaction with registry vs an indirect interaction with registry, these cases should be handled. |
|
@anusha-ragunathan Good point, I had not thought of that but I agree we should handle it. I think if we merge this PR and then merge @aaronlehmann 's (as of yet uncreated) PR for |
|
I just updated the PR with a better test given that the format of the UA "concatenation" has changed to a backslash-escaped, embedded string. I know the test is not perfect and only looks at the beginning of each string, but I don't want to make the integration tests too brittle. Open to suggestions if anyone has them. |
dockerversion/useragent.go
Outdated
There was a problem hiding this comment.
Typo: should be insertUpstreamUserAgent.
The main problem that I see with the test is that it will succeed even if the mock handler is never hit for some reason. I've corrected this in my followup PR, so don't worry about it in this one. |
|
Hi @aaronlehmann, I see how your branch improves the test significantly, so I'm going to defer to your PR on that. |
|
All other tests passing. |
Changes how the Engine interacts with Registry servers on image pull. Previously, Engine sent a User-Agent string to the Registry server that included only the Engine's version information. This commit appends to that string the fields from the User-Agent sent by the client (e.g., Compose) of the Engine. This allows Registry server operators to understand what tools are actually generating pulls on their registries. Signed-off-by: Mike Goelzer <mgoelzer@docker.com>
|
@mgoelzer Sorry for this, the win2lin issue is known and being worked on, the windowsTP4 unfortunately has no solution but wait for a better TP release. I'll rebuild, we'll get it green. |
|
@icecrime, no problem. I'm just posting the output of failing tests so we have a log of what's failing. But since it seems to be sporadic, there's probably no point. |
|
@mgoelzer : I'm okay with you fixing pull on build/run in a subsequent PR. It'd be nice to get that in 1.11 as well, but I understand if there are timing constraints. |
|
@icecrime If we can get this merged today, @aaronlehmann has a second PR he will open that adds the User-Agent stuff to |
|
LGTM |
| appended := false | ||
| for _, escapeableRune := range charsToEscape { | ||
| if currRune == escapeableRune { | ||
| ret += "\\" + string(currRune) |
There was a problem hiding this comment.
Why is this double escaped? If it encounters ;, it should emit \;. If it encounters \, it should emit \\.
There was a problem hiding this comment.
Not sure what you mean by double escaped. The string literal "\" is a one-character string. So, encountering ; will cause it to append to ret \;, like you're saying.
EDIT: ironically, I can't say what I want because github also escapes backslashes :-)
There was a problem hiding this comment.
Rather, use a bactic literal here for clarity.
There was a problem hiding this comment.
To save CI churn, I'd be happy to make this change in my followup PR.
|
LGTM |
1 similar comment
|
LGTM |
Pass upstream client's user agent through to registry on image pulls
|
Opened the companion PR to extend this to build, login, push, and search here: #21373 |
|
👍 |
Summary: pass through to registry an upstream user-agent on image pull. Closes issue #20001.
What I did: People running Registry servers should be able to see what client initiated an image pull per issue #20001. For example, if Compose instructs Engine to pull from a local Registry, then the User-Agent header sent to that Registry server should be the following RFC 7231 compliant [1] string concatenation:
upstream-ua/end;is just a delimiter. (Open to suggestions for a better one.)How I did it: When Engine receives an image pull API request, I set a
golang.org/x/net/contextcontext inside the closure returned byNewUserAgentMiddleware()inapi/server/middleware/user_agent.go. This context includes the upstream client's UA string (e.g., Compose's UA string). From there, I just plumbed thecontextvariable all the way through the request processing chain untilDockerUserAgent()is called.DockerUserAgent()was modified to accept an optional string argument, which is read back from thecontextby the caller.How to verify it:
See [2] for more information.
Refs:
[1] RFC 7231: http://tools.ietf.org/html/rfc7231#section-5.5.3
[2] https://github.com/docker/distribution/blob/master/docs/deploying.md