diff --git a/api/swagger.yaml b/api/swagger.yaml index b58310f327..5677340dbd 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -8774,8 +8774,7 @@ paths:


- > **Deprecated**: This field is deprecated and will always - > be "false" in future. + > **Deprecated**: This field is deprecated and will always be "false". type: "boolean" example: false name: @@ -8818,13 +8817,8 @@ paths: description: | A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters: - - `is-automated=(true|false)` (deprecated, see below) - `is-official=(true|false)` - `stars=` Matches images that has at least 'number' stars. - - The `is-automated` filter is deprecated. The `is_automated` field has - been deprecated by Docker Hub's search API. Consequently, searching - for `is-automated=true` will yield no results. type: "string" tags: ["Image"] /images/prune: diff --git a/api/types/registry/registry.go b/api/types/registry/registry.go index 05cb31075f..6bbae93ef2 100644 --- a/api/types/registry/registry.go +++ b/api/types/registry/registry.go @@ -94,7 +94,7 @@ type SearchResult struct { Name string `json:"name"` // IsAutomated indicates whether the result is automated. // - // Deprecated: the "is_automated" field is deprecated and will always be "false" in the future. + // Deprecated: the "is_automated" field is deprecated and will always be "false". IsAutomated bool `json:"is_automated"` // Description is a textual description of the repository Description string `json:"description"` diff --git a/docs/api/version-history.md b/docs/api/version-history.md index b1f701b74b..a91d01237e 100644 --- a/docs/api/version-history.md +++ b/docs/api/version-history.md @@ -19,6 +19,9 @@ keywords: "API, Docker, rcli, REST, documentation" * `POST /containers/create` now supports `VolumeOptions.Subpath` which allows a subpath of a named volume to be mounted. +* `POST /images/search` will always assume a `false` value for the `is-automated` + field. Consequently, searching for `is-automated=true` will yield no results, + while `is-automated=false` will be a no-op. ## v1.44 API changes diff --git a/integration-cli/docker_cli_search_test.go b/integration-cli/docker_cli_search_test.go index 09c3a85720..2a0691bbf4 100644 --- a/integration-cli/docker_cli_search_test.go +++ b/integration-cli/docker_cli_search_test.go @@ -8,6 +8,7 @@ import ( "github.com/docker/docker/integration-cli/cli" "gotest.tools/v3/assert" + is "gotest.tools/v3/assert/cmp" ) type DockerCLISearchSuite struct { @@ -52,9 +53,9 @@ func (s *DockerCLISearchSuite) TestSearchCmdOptions(c *testing.T) { outSearchCmdautomated := cli.DockerCmd(c, "search", "--filter", "is-automated=true", "busybox").Combined() // The busybox is a busybox base image, not an AUTOMATED image. outSearchCmdautomatedSlice := strings.Split(outSearchCmdautomated, "\n") - for i := range outSearchCmdautomatedSlice { - assert.Assert(c, !strings.HasPrefix(outSearchCmdautomatedSlice[i], "busybox "), "The busybox is not an AUTOMATED image: %s", outSearchCmdautomated) - } + + // is-automated=true should produce no results (only a header) + assert.Check(c, is.Len(outSearchCmdautomatedSlice, 2)) outSearchCmdNotOfficial := cli.DockerCmd(c, "search", "--filter", "is-official=false", "busybox").Combined() // The busybox is a busybox base image, official image. outSearchCmdNotOfficialSlice := strings.Split(outSearchCmdNotOfficial, "\n") diff --git a/registry/search.go b/registry/search.go index 75a5444109..5c79e9968b 100644 --- a/registry/search.go +++ b/registry/search.go @@ -27,11 +27,16 @@ func (s *Service) Search(ctx context.Context, searchFilters filters.Args, term s return nil, err } - // TODO(thaJeztah): the "is-automated" field is deprecated; reset the field for the next release (v26.0.0). Return early when using "is-automated=true", and ignore "is-automated=false". isAutomated, err := searchFilters.GetBoolOrDefault("is-automated", false) if err != nil { return nil, err } + + // "is-automated" is deprecated and filtering for `true` will yield no results. + if isAutomated { + return []registry.SearchResult{}, nil + } + isOfficial, err := searchFilters.GetBoolOrDefault("is-official", false) if err != nil { return nil, err @@ -51,7 +56,6 @@ func (s *Service) Search(ctx context.Context, searchFilters filters.Args, term s } } - // TODO(thaJeztah): the "is-automated" field is deprecated. Reset the field for the next release (v26.0.0) if any "true" values are present. unfilteredResult, err := s.searchUnfiltered(ctx, term, limit, authConfig, headers) if err != nil { return nil, err @@ -59,11 +63,6 @@ func (s *Service) Search(ctx context.Context, searchFilters filters.Args, term s filteredResults := []registry.SearchResult{} for _, result := range unfilteredResult.Results { - if searchFilters.Contains("is-automated") { - if isAutomated != result.IsAutomated { //nolint:staticcheck // ignore SA1019 for old API versions. - continue - } - } if searchFilters.Contains("is-official") { if isOfficial != result.IsOfficial { continue @@ -74,6 +73,10 @@ func (s *Service) Search(ctx context.Context, searchFilters filters.Args, term s continue } } + // "is-automated" is deprecated and the value in Docker Hub search + // results is untrustworthy. Force it to false so as to not mislead our + // clients. + result.IsAutomated = false //nolint:staticcheck // ignore SA1019 (field is deprecated) filteredResults = append(filteredResults, result) } diff --git a/registry/search_test.go b/registry/search_test.go index f9e1bd95ed..82b7757963 100644 --- a/registry/search_test.go +++ b/registry/search_test.go @@ -206,16 +206,10 @@ func TestSearch(t *testing.T) { IsAutomated: true, //nolint:staticcheck // ignore SA1019 (field is deprecated). }, }, - expectedResults: []registry.SearchResult{ - { - Name: "name", - Description: "description", - IsAutomated: true, //nolint:staticcheck // ignore SA1019 (field is deprecated). - }, - }, + expectedResults: []registry.SearchResult{}, }, { - name: "is-automated=false, no results", + name: "is-automated=false, IsAutomated reset to false", filtersArgs: filters.NewArgs(filters.Arg("is-automated", "false")), registryResults: []registry.SearchResult{ { @@ -224,7 +218,13 @@ func TestSearch(t *testing.T) { IsAutomated: true, //nolint:staticcheck // ignore SA1019 (field is deprecated). }, }, - expectedResults: []registry.SearchResult{}, + expectedResults: []registry.SearchResult{ + { + Name: "name", + Description: "description", + IsAutomated: false, //nolint:staticcheck // ignore SA1019 (field is deprecated). + }, + }, }, { name: "is-automated=false", @@ -390,15 +390,7 @@ func TestSearch(t *testing.T) { IsAutomated: true, //nolint:staticcheck // ignore SA1019 (field is deprecated). }, }, - expectedResults: []registry.SearchResult{ - { - Name: "name3", - Description: "description3", - StarCount: 2, - IsOfficial: true, - IsAutomated: true, //nolint:staticcheck // ignore SA1019 (field is deprecated). - }, - }, + expectedResults: []registry.SearchResult{}, }, } for _, tc := range successCases {