Skip to content

Move filtered registry search out of the image service#45086

Merged
neersighted merged 2 commits intomoby:masterfrom
corhere:search-in-registry-service
Mar 15, 2023
Merged

Move filtered registry search out of the image service#45086
neersighted merged 2 commits intomoby:masterfrom
corhere:search-in-registry-service

Conversation

@corhere
Copy link
Copy Markdown
Contributor

@corhere corhere commented Mar 1, 2023

Move filtered registry search logic out of the image service as querying a remote registry is unrelated to the functionality of the image service. Move the logic into the registry service as it is the source of truth for the registry configuration, which makes it the most cohesive place to put it which does not require more extensive refactoring.

@corhere corhere added area/api API area/distribution Image Distribution status/2-code-review area/images Image Distribution kind/refactor PR's that refactor, or clean-up code containerd-integration Issues and PRs related to containerd integration labels Mar 1, 2023
@thaJeztah
Copy link
Copy Markdown
Member

I'm leaning towards keeping this more separate from the registry; "search" is a bit of an odd one, because search is not part of the OCI distribution specification.

Search was implemented in "docker registry v1" (the Docker Index (hence index.docker.io), which later became Docker Hub). When the registry V2 specification was created (which became the OCI Distribution Spec), search was deliberately left out of the implementation, because indexing and searching content was a separate concern, and it became clear that "what can be searched", "how" can be searched (and what properties to search for) could be very opinionated (different providers could have different things to search for).

So search did not become part of the OCI specs.

The search functionality in the daemon is still in place mostly for backward compatibility, and because the old (v1) search API is the only documented search API, so some other registry implementations also added support for it (by lack of other specifications for searching).

That said; some registries (including Docker Hub) provide other (more advanced) search functionality, and there's been some talk about defining a OCI spec for searching/indexing (not sure if that ever got actual progress though).

With the above in mind, I'd like to keep it separate with the potential to;

  • Allow other implementations to be added (haven't given this much thought, but somehow making it pluggable?)
  • (there's been various discussions about "better search" for images on Docker Hub at least; Docker Hub already has V2 and V3 search engines, which could provide some of that, but not sure if their API is publicly documented).
  • Probably for backward-compat, the "fallback" would be to use the V1 search

In either case; my thinking was to "try to keep it as isolated as possible"

@corhere corhere changed the title Move filtered registry search into registry service Move filtered registry search out of the image service Mar 1, 2023
@corhere
Copy link
Copy Markdown
Contributor Author

corhere commented Mar 1, 2023

I'm leaning towards keeping this more separate from the registry; "search" is a bit of an odd one, because search is not part of the OCI distribution specification.

The search interface is separated from the image distribution interface. The implementation is tied to the registry service, but that was already the case. Think of this PR as more of "getting search out of the wrong place to unblock containerd integration" than "getting search into the perfect place." We can still make #44032 happen; this PR just takes the pressure off.

@corhere corhere force-pushed the search-in-registry-service branch from adfc66d to 55213f7 Compare March 1, 2023 22:42
Copy link
Copy Markdown
Member

@rumpl rumpl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, a great first step, and love that it unblocks containerd a bit. Thanks

@corhere corhere requested a review from neersighted March 2, 2023 20:47
Copy link
Copy Markdown
Member

@tianon tianon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that somewhere else is probably better, but also that "registry" seems like a more appropriate home than the image store for this Hub-specific behavior (given Hub is a registry, even if this isn't an OCI-specified endpoint). 😅

(In other words, this seems like a very small, easy net win on the path to that larger reconsideration ❤️)

Copy link
Copy Markdown
Member

@neersighted neersighted left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a sensible cleanup/separation of concerns to me, and eases the containerd integration work. Needs a rebase, but otherwise LGTM.

@neersighted neersighted added this to the v-next milestone Mar 10, 2023
corhere added 2 commits March 10, 2023 18:36
SearchRegistryForImages does not make sense as part of the image
service interface. The implementation just wraps the search API of the
registry service to filter the results client-side. It has nothing to do
with local image storage, and the implementation of search does not need
to change when changing which backend (graph driver vs. containerd
snapshotter) is used for local image storage.

Filtering of the search results is an implementation detail: the
consumer of the results does not care which actor does the filtering so
long as the results are filtered as requested. Move filtering into the
exported API of the registry service to hide the implementation details.
Only one thing---the registry service implementation---would need to
change in order to support server-side filtering of search results if
Docker Hub or other registry servers were to add support for it to their
APIs.

Use a fake registry server in the search unit tests to avoid having to
mock out the registry API client.

Signed-off-by: Cory Snider <[email protected]>
@corhere corhere force-pushed the search-in-registry-service branch from 55213f7 to 7b3acdf Compare March 10, 2023 23:38

"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/dockerversion"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import causes the CLI to also pull in docker/cli@a5d122d (commit vendoring is from a temporary branch, so link will likely be broken at some point);

  • github.com/docker/docker/dockerversion
    • -> github.com/docker/docker/pkg/useragent
    • -> github.com/docker/docker/pkg/parsers/kernel
    • -> golang.org/x/sys/windows/registry

We'll probably need to have a look at passing the dockerversion / dockerversion.DockerUserAgent(ctx) somehow

/cc @corhere @neersighted

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, shoot, interesting.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, TBH, the whole dockerversion.DockerUserAgent() (or more specifically, why it's added here?) is a bit weird. If I'm not mistaken, it takes the client's user-agent, and appends the "daemon" user-agent (so that both the "upstream" client (e.g. docker CLI), and the daemon are included.

Overall that seems fine, but definitely feels like something that should be set when constructing the service (or perhaps to be passed when calling it). Haven't looked how we handle this for the other "registry" cases (docker pull / docker push).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick search for that;

When Authenticating;

moby/daemon/auth.go

Lines 11 to 13 in a082bbc

func (daemon *Daemon) AuthenticateToRegistry(ctx context.Context, authConfig *registry.AuthConfig) (string, string, error) {
return daemon.registryService.Auth(ctx, authConfig, dockerversion.DockerUserAgent(ctx))
}

Distribution sets it up as part of the transport;

modifiers := registry.Headers(dockerversion.DockerUserAgent(ctx), metaHeaders)
authTransport := transport.NewTransport(base, modifiers...)

And for plugins;

moby/plugin/registry.go

Lines 30 to 34 in a082bbc

func (pm *Manager) newResolver(ctx context.Context, tracker docker.StatusTracker, auth *registry.AuthConfig, headers http.Header, httpFallback bool) (remotes.Resolver, error) {
if headers == nil {
headers = http.Header{}
}
headers.Add("User-Agent", dockerversion.DockerUserAgent(ctx))

So looks like it's a bit "all over the place"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api API area/distribution Image Distribution area/images Image Distribution containerd-integration Issues and PRs related to containerd integration kind/refactor PR's that refactor, or clean-up code status/4-merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants