diff --git a/docs/registry_test.go b/docs/registry_test.go index 39a01bcd..9927af32 100644 --- a/docs/registry_test.go +++ b/docs/registry_test.go @@ -730,7 +730,7 @@ func TestPushImageJSONIndex(t *testing.T) { func TestSearchRepositories(t *testing.T) { r := spawnTestRegistrySession(t) - results, err := r.SearchRepositories("fakequery") + results, err := r.SearchRepositories("fakequery", 25) if err != nil { t.Fatal(err) } diff --git a/docs/service.go b/docs/service.go index d48063cd..25b4990e 100644 --- a/docs/service.go +++ b/docs/service.go @@ -15,6 +15,11 @@ import ( registrytypes "github.com/docker/engine-api/types/registry" ) +const ( + // DefaultSearchLimit is the default value for maximum number of returned search results. + DefaultSearchLimit = 25 +) + // Service is the interface defining what a registry service should implement. type Service interface { Auth(ctx context.Context, authConfig *types.AuthConfig, userAgent string) (status, token string, err error) @@ -22,7 +27,7 @@ type Service interface { LookupPushEndpoints(hostname string) (endpoints []APIEndpoint, err error) ResolveRepository(name reference.Named) (*RepositoryInfo, error) ResolveIndex(name string) (*registrytypes.IndexInfo, error) - Search(ctx context.Context, term string, authConfig *types.AuthConfig, userAgent string, headers map[string][]string) (*registrytypes.SearchResults, error) + Search(ctx context.Context, term string, limit int, authConfig *types.AuthConfig, userAgent string, headers map[string][]string) (*registrytypes.SearchResults, error) ServiceConfig() *registrytypes.ServiceConfig TLSConfig(hostname string) (*tls.Config, error) } @@ -108,7 +113,7 @@ func splitReposSearchTerm(reposName string) (string, string) { // Search queries the public registry for images matching the specified // search terms, and returns the results. -func (s *DefaultService) Search(ctx context.Context, term string, authConfig *types.AuthConfig, userAgent string, headers map[string][]string) (*registrytypes.SearchResults, error) { +func (s *DefaultService) Search(ctx context.Context, term string, limit int, authConfig *types.AuthConfig, userAgent string, headers map[string][]string) (*registrytypes.SearchResults, error) { // TODO Use ctx when searching for repositories if err := validateNoScheme(term); err != nil { return nil, err @@ -139,9 +144,9 @@ func (s *DefaultService) Search(ctx context.Context, term string, authConfig *ty localName = strings.SplitN(localName, "/", 2)[1] } - return r.SearchRepositories(localName) + return r.SearchRepositories(localName, limit) } - return r.SearchRepositories(remoteName) + return r.SearchRepositories(remoteName, limit) } // ResolveRepository splits a repository name into its components diff --git a/docs/session.go b/docs/session.go index 82593cd7..140c458e 100644 --- a/docs/session.go +++ b/docs/session.go @@ -721,9 +721,12 @@ func shouldRedirect(response *http.Response) bool { } // SearchRepositories performs a search against the remote repository -func (r *Session) SearchRepositories(term string) (*registrytypes.SearchResults, error) { +func (r *Session) SearchRepositories(term string, limit int) (*registrytypes.SearchResults, error) { + if limit < 1 || limit > 100 { + return nil, fmt.Errorf("Limit %d is outside the range of [1, 100]", limit) + } logrus.Debugf("Index server: %s", r.indexEndpoint) - u := r.indexEndpoint.String() + "search?q=" + url.QueryEscape(term) + u := r.indexEndpoint.String() + "search?q=" + url.QueryEscape(term) + "&n=" + url.QueryEscape(fmt.Sprintf("%d", limit)) req, err := http.NewRequest("GET", u, nil) if err != nil {