1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Add a --filter option to docker search

The filtering is made server-side, and the following filters are
supported:

* is-official (boolean)
* is-automated (boolean)
* has-stars (integer)

Signed-off-by: Fabrizio Soppelsa <fsoppelsa@mirantis.com>
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
Fabrizio Soppelsa 2016-05-20 13:41:28 +02:00 committed by Vincent Demeester
parent 0e9009bae3
commit e009ebdf4c
No known key found for this signature in database
GPG key ID: 083CC6FD6EB699A3
12 changed files with 272 additions and 49 deletions

View file

@ -10,10 +10,12 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
Cli "github.com/docker/docker/cli" Cli "github.com/docker/docker/cli"
"github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag" flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/stringutils" "github.com/docker/docker/pkg/stringutils"
"github.com/docker/docker/registry" "github.com/docker/docker/registry"
"github.com/docker/engine-api/types" "github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
registrytypes "github.com/docker/engine-api/types/registry" registrytypes "github.com/docker/engine-api/types/registry"
) )
@ -21,14 +23,32 @@ import (
// //
// Usage: docker search [OPTIONS] TERM // Usage: docker search [OPTIONS] TERM
func (cli *DockerCli) CmdSearch(args ...string) error { func (cli *DockerCli) CmdSearch(args ...string) error {
var (
err error
filterArgs = filters.NewArgs()
flFilter = opts.NewListOpts(nil)
)
cmd := Cli.Subcmd("search", []string{"TERM"}, Cli.DockerCommands["search"].Description, true) cmd := Cli.Subcmd("search", []string{"TERM"}, Cli.DockerCommands["search"].Description, true)
noTrunc := cmd.Bool([]string{"-no-trunc"}, false, "Don't truncate output") noTrunc := cmd.Bool([]string{"-no-trunc"}, false, "Don't truncate output")
automated := cmd.Bool([]string{"-automated"}, false, "Only show automated builds") cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided")
stars := cmd.Uint([]string{"s", "-stars"}, 0, "Only displays with at least x stars")
// Deprecated since Docker 1.12 in favor of "--filter"
automated := cmd.Bool([]string{"#-automated"}, false, "Only show automated builds - DEPRECATED")
stars := cmd.Uint([]string{"s", "#-stars"}, 0, "Only displays with at least x stars - DEPRECATED")
cmd.Require(flag.Exact, 1) cmd.Require(flag.Exact, 1)
cmd.ParseFlags(args, true) cmd.ParseFlags(args, true)
for _, f := range flFilter.GetAll() {
if filterArgs, err = filters.ParseFlag(f, filterArgs); err != nil {
return err
}
}
name := cmd.Arg(0) name := cmd.Arg(0)
v := url.Values{} v := url.Values{}
v.Set("term", name) v.Set("term", name)
@ -49,6 +69,7 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
options := types.ImageSearchOptions{ options := types.ImageSearchOptions{
RegistryAuth: encodedAuth, RegistryAuth: encodedAuth,
PrivilegeFunc: requestPrivilege, PrivilegeFunc: requestPrivilege,
Filters: filterArgs,
} }
unorderedResults, err := cli.client.ImageSearch(context.Background(), name, options) unorderedResults, err := cli.client.ImageSearch(context.Background(), name, options)
@ -62,6 +83,7 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
w := tabwriter.NewWriter(cli.out, 10, 1, 3, ' ', 0) w := tabwriter.NewWriter(cli.out, 10, 1, 3, ' ', 0)
fmt.Fprintf(w, "NAME\tDESCRIPTION\tSTARS\tOFFICIAL\tAUTOMATED\n") fmt.Fprintf(w, "NAME\tDESCRIPTION\tSTARS\tOFFICIAL\tAUTOMATED\n")
for _, res := range results { for _, res := range results {
// --automated and -s, --stars are deprecated since Docker 1.12
if (*automated && !res.IsAutomated) || (int(*stars) > res.StarCount) { if (*automated && !res.IsAutomated) || (int(*stars) > res.StarCount) {
continue continue
} }

View file

@ -39,5 +39,5 @@ type importExportBackend interface {
type registryBackend interface { type registryBackend interface {
PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
SearchRegistryForImages(ctx context.Context, term string, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registry.SearchResults, error) SearchRegistryForImages(ctx context.Context, filtersArgs string, term string, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registry.SearchResults, error)
} }

View file

@ -301,7 +301,7 @@ func (s *imageRouter) getImagesSearch(ctx context.Context, w http.ResponseWriter
headers[k] = v headers[k] = v
} }
} }
query, err := s.backend.SearchRegistryForImages(ctx, r.Form.Get("term"), config, headers) query, err := s.backend.SearchRegistryForImages(ctx, r.Form.Get("filters"), r.Form.Get("term"), config, headers)
if err != nil { if err != nil {
return err return err
} }

View file

@ -1907,15 +1907,29 @@ _docker_save() {
} }
_docker_search() { _docker_search() {
local key=$(__docker_map_key_of_current_option '--filter|-f')
case "$key" in
is-automated)
COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) )
return
;;
is-official)
COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) )
return
;;
esac
case "$prev" in case "$prev" in
--stars|-s) --filter|-f)
COMPREPLY=( $( compgen -S = -W "is-automated is-official stars" -- "$cur" ) )
__docker_nospace
return return
;; ;;
esac esac
case "$cur" in case "$cur" in
-*) -*)
COMPREPLY=( $( compgen -W "--automated --help --no-trunc --stars -s" -- "$cur" ) ) COMPREPLY=( $( compgen -W "--filter --help --no-trunc" -- "$cur" ) )
;; ;;
esac esac
} }

View file

@ -311,6 +311,30 @@ __docker_complete_ps_filters() {
return ret return ret
} }
__docker_complete_search_filters() {
[[ $PREFIX = -* ]] && return 1
integer ret=1
declare -a boolean_opts opts
boolean_opts=('true' 'false')
opts=('is-automated' 'is-official' 'stars')
if compset -P '*='; then
case "${${words[-1]%=*}#*=}" in
(is-automated|is-official)
_describe -t boolean-filter-opts "filter options" boolean_opts && ret=0
;;
*)
_message 'value' && ret=0
;;
esac
else
_describe -t filter-opts "filter options" opts -qS "=" && ret=0
fi
return ret
}
__docker_network_complete_ls_filters() { __docker_network_complete_ls_filters() {
[[ $PREFIX = -* ]] && return 1 [[ $PREFIX = -* ]] && return 1
integer ret=1 integer ret=1
@ -1126,10 +1150,15 @@ __docker_subcommand() {
(search) (search)
_arguments $(__docker_arguments) \ _arguments $(__docker_arguments) \
$opts_help \ $opts_help \
"($help)--automated[Only show automated builds]" \ "($help)*"{-f=,--filter=}"[Filter values]:filter:->filter-options" \
"($help)--no-trunc[Do not truncate output]" \ "($help)--no-trunc[Do not truncate output]" \
"($help -s --stars)"{-s=,--stars=}"[Only display with at least X stars]:stars:(0 10 100 1000)" \
"($help -):term: " && ret=0 "($help -):term: " && ret=0
case $state in
(filter-options)
__docker_complete_search_filters && ret=0
;;
esac
;; ;;
(start) (start)
_arguments $(__docker_arguments) \ _arguments $(__docker_arguments) \

View file

@ -15,6 +15,7 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime" "runtime"
"strconv"
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
@ -64,6 +65,7 @@ import (
volumedrivers "github.com/docker/docker/volume/drivers" volumedrivers "github.com/docker/docker/volume/drivers"
"github.com/docker/docker/volume/local" "github.com/docker/docker/volume/local"
"github.com/docker/docker/volume/store" "github.com/docker/docker/volume/store"
"github.com/docker/engine-api/types/filters"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/docker/libnetwork" "github.com/docker/libnetwork"
nwconfig "github.com/docker/libnetwork/config" nwconfig "github.com/docker/libnetwork/config"
@ -1427,12 +1429,85 @@ func (daemon *Daemon) AuthenticateToRegistry(ctx context.Context, authConfig *ty
return daemon.RegistryService.Auth(authConfig, dockerversion.DockerUserAgent(ctx)) return daemon.RegistryService.Auth(authConfig, dockerversion.DockerUserAgent(ctx))
} }
var acceptedSearchFilterTags = map[string]bool{
"is-automated": true,
"is-official": true,
"stars": true,
}
// SearchRegistryForImages queries the registry for images matching // SearchRegistryForImages queries the registry for images matching
// term. authConfig is used to login. // term. authConfig is used to login.
func (daemon *Daemon) SearchRegistryForImages(ctx context.Context, term string, func (daemon *Daemon) SearchRegistryForImages(ctx context.Context, filtersArgs string, term string,
authConfig *types.AuthConfig, authConfig *types.AuthConfig,
headers map[string][]string) (*registrytypes.SearchResults, error) { headers map[string][]string) (*registrytypes.SearchResults, error) {
return daemon.RegistryService.Search(term, authConfig, dockerversion.DockerUserAgent(ctx), headers)
searchFilters, err := filters.FromParam(filtersArgs)
if err != nil {
return nil, err
}
if err := searchFilters.Validate(acceptedSearchFilterTags); err != nil {
return nil, err
}
unfilteredResult, err := daemon.RegistryService.Search(term, authConfig, dockerversion.DockerUserAgent(ctx), headers)
if err != nil {
return nil, err
}
var isAutomated, isOfficial bool
var hasStarFilter = 0
if searchFilters.Include("is-automated") {
if searchFilters.ExactMatch("is-automated", "true") {
isAutomated = true
} else if !searchFilters.ExactMatch("is-automated", "false") {
return nil, fmt.Errorf("Invalid filter 'is-automated=%s'", searchFilters.Get("is-automated"))
}
}
if searchFilters.Include("is-official") {
if searchFilters.ExactMatch("is-official", "true") {
isOfficial = true
} else if !searchFilters.ExactMatch("is-official", "false") {
return nil, fmt.Errorf("Invalid filter 'is-official=%s'", searchFilters.Get("is-official"))
}
}
if searchFilters.Include("stars") {
hasStars := searchFilters.Get("stars")
for _, hasStar := range hasStars {
iHasStar, err := strconv.Atoi(hasStar)
if err != nil {
return nil, fmt.Errorf("Invalid filter 'stars=%s'", hasStar)
}
if iHasStar > hasStarFilter {
hasStarFilter = iHasStar
}
}
}
filteredResults := []registrytypes.SearchResult{}
for _, result := range unfilteredResult.Results {
if searchFilters.Include("is-automated") {
if isAutomated != result.IsAutomated {
continue
}
}
if searchFilters.Include("is-official") {
if isOfficial != result.IsOfficial {
continue
}
}
if searchFilters.Include("stars") {
if result.StarCount < hasStarFilter {
continue
}
}
filteredResults = append(filteredResults, result)
}
return &registrytypes.SearchResults{
Query: unfilteredResult.Query,
NumResults: len(filteredResults),
Results: filteredResults,
}, nil
} }
// IsShuttingDown tells whether the daemon is shutting down or not // IsShuttingDown tells whether the daemon is shutting down or not

View file

@ -58,6 +58,15 @@ defining it at container creation (`POST /containers/create`).
The `docker ps --before` and `docker ps --since` options are deprecated. The `docker ps --before` and `docker ps --since` options are deprecated.
Use `docker ps --filter=before=...` and `docker ps --filter=since=...` instead. Use `docker ps --filter=before=...` and `docker ps --filter=since=...` instead.
### Docker search 'automated' and 'stars' options
**Deprecated in Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)**
**Removed In Release: v1.14**
The `docker search --automated` and `docker search --stars` options are deprecated.
Use `docker search --filter=is-automated=...` and `docker search --filter=stars=...` instead.
### Command line short variant options ### Command line short variant options
**Deprecated In Release: v1.9** **Deprecated In Release: v1.9**

View file

@ -118,6 +118,7 @@ This section lists each version from latest to oldest. Each listing includes a
* `POST /containers/create` now takes `MaximumIOps` and `MaximumIOBps` fields. Windows daemon only. * `POST /containers/create` now takes `MaximumIOps` and `MaximumIOBps` fields. Windows daemon only.
* `POST /containers/create` now returns a HTTP 400 "bad parameter" message * `POST /containers/create` now returns a HTTP 400 "bad parameter" message
if no command is specified (instead of a HTTP 500 "server error") if no command is specified (instead of a HTTP 500 "server error")
* `GET /images/search` now takes a `filters` query parameter.
### v1.23 API changes ### v1.23 API changes

View file

@ -2133,6 +2133,10 @@ Search for an image on [Docker Hub](https://hub.docker.com).
Query Parameters: Query Parameters:
- **term** term to search - **term** term to search
- **filters** a JSON encoded value of the filters (a map[string][]string) to process on the images list. Available filters:
- `stars=<number>`
- `is-automated=(true|false)`
- `is-official=(true|false)`
Status Codes: Status Codes:

View file

@ -14,10 +14,12 @@ parent = "smn_cli"
Search the Docker Hub for images Search the Docker Hub for images
--automated Only show automated builds --filter=[] Filter output based on these conditions:
- is-automated=(true|false)
- is-official=(true|false)
- stars=<number> - image has at least 'number' stars
--help Print usage --help Print usage
--no-trunc Don't truncate output --no-trunc Don't truncate output
-s, --stars=0 Only displays with at least x stars
Search [Docker Hub](https://hub.docker.com) for images Search [Docker Hub](https://hub.docker.com) for images
@ -61,29 +63,6 @@ This example displays images with a name containing 'busybox':
scottabernethy/busybox 0 [OK] scottabernethy/busybox 0 [OK]
marclop/busybox-solr marclop/busybox-solr
### Search images by name and number of stars (-s, --stars)
This example displays images with a name containing 'busybox' and at
least 3 stars:
$ docker search --stars=3 busybox
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
busybox Busybox base image. 325 [OK]
progrium/busybox 50 [OK]
radial/busyboxplus Full-chain, Internet enabled, busybox made... 8 [OK]
### Search automated images (--automated)
This example displays images with a name containing 'busybox', at
least 3 stars and are automated builds:
$ docker search --stars=3 --automated busybox
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
progrium/busybox 50 [OK]
radial/busyboxplus Full-chain, Internet enabled, busybox made... 8 [OK]
### Display non-truncated description (--no-trunc) ### Display non-truncated description (--no-trunc)
This example displays images with a name containing 'busybox', This example displays images with a name containing 'busybox',
@ -95,3 +74,48 @@ at least 3 stars and the description isn't truncated in the output:
progrium/busybox 50 [OK] progrium/busybox 50 [OK]
radial/busyboxplus Full-chain, Internet enabled, busybox made from scratch. Comes in git and cURL flavors. 8 [OK] radial/busyboxplus Full-chain, Internet enabled, busybox made from scratch. Comes in git and cURL flavors. 8 [OK]
## Filtering
The filtering flag (`-f` or `--filter`) format is a `key=value` pair. If there is more
than one filter, then pass multiple flags (e.g. `--filter "foo=bar" --filter "bif=baz"`)
The currently supported filters are:
* stars (int - number of stars the image has)
* is-automated (true|false) - is the image automated or not
* is-official (true|false) - is the image official or not
### stars
This example displays images with a name containing 'busybox' and at
least 3 stars:
$ docker search --filter stars=3 busybox
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
busybox Busybox base image. 325 [OK]
progrium/busybox 50 [OK]
radial/busyboxplus Full-chain, Internet enabled, busybox made... 8 [OK]
### is-automated
This example displays images with a name containing 'busybox'
and are automated builds:
$ docker search --filter is-automated busybox
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
progrium/busybox 50 [OK]
radial/busyboxplus Full-chain, Internet enabled, busybox made... 8 [OK]
### is-official
This example displays images with a name containing 'busybox', at least
3 stars and are official builds:
$ docker search --filter "is-automated=true" --filter "stars=3" busybox
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
progrium/busybox 50 [OK]
radial/busyboxplus Full-chain, Internet enabled, busybox made... 8 [OK]

View file

@ -16,34 +16,78 @@ func (s *DockerSuite) TestSearchOnCentralRegistry(c *check.C) {
} }
func (s *DockerSuite) TestSearchStarsOptionWithWrongParameter(c *check.C) { func (s *DockerSuite) TestSearchStarsOptionWithWrongParameter(c *check.C) {
out, _, err := dockerCmdWithError("search", "--stars=a", "busybox") out, _, err := dockerCmdWithError("search", "--filter", "stars=a", "busybox")
c.Assert(err, check.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Invalid filter", check.Commentf("couldn't find the invalid filter warning"))
out, _, err = dockerCmdWithError("search", "-f", "stars=a", "busybox")
c.Assert(err, check.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Invalid filter", check.Commentf("couldn't find the invalid filter warning"))
out, _, err = dockerCmdWithError("search", "-f", "is-automated=a", "busybox")
c.Assert(err, check.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Invalid filter", check.Commentf("couldn't find the invalid filter warning"))
out, _, err = dockerCmdWithError("search", "-f", "is-official=a", "busybox")
c.Assert(err, check.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Invalid filter", check.Commentf("couldn't find the invalid filter warning"))
// -s --stars deprecated since Docker 1.13
out, _, err = dockerCmdWithError("search", "--stars=a", "busybox")
c.Assert(err, check.NotNil, check.Commentf(out)) c.Assert(err, check.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "invalid value", check.Commentf("couldn't find the invalid value warning")) c.Assert(out, checker.Contains, "invalid value", check.Commentf("couldn't find the invalid value warning"))
// -s --stars deprecated since Docker 1.13
out, _, err = dockerCmdWithError("search", "-s=-1", "busybox") out, _, err = dockerCmdWithError("search", "-s=-1", "busybox")
c.Assert(err, check.NotNil, check.Commentf(out)) c.Assert(err, check.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "invalid value", check.Commentf("couldn't find the invalid value warning")) c.Assert(out, checker.Contains, "invalid value", check.Commentf("couldn't find the invalid value warning"))
} }
func (s *DockerSuite) TestSearchCmdOptions(c *check.C) { func (s *DockerSuite) TestSearchCmdOptions(c *check.C) {
testRequires(c, Network) testRequires(c, Network, DaemonIsLinux)
out, _ := dockerCmd(c, "search", "--help") out, _ := dockerCmd(c, "search", "--help")
c.Assert(out, checker.Contains, "Usage:\tdocker search [OPTIONS] TERM") c.Assert(out, checker.Contains, "Usage:\tdocker search [OPTIONS] TERM")
outSearchCmd, _ := dockerCmd(c, "search", "busybox") outSearchCmd, _ := dockerCmd(c, "search", "busybox")
outSearchCmdNotrunc, _ := dockerCmd(c, "search", "--no-trunc=true", "busybox") outSearchCmdNotrunc, _ := dockerCmd(c, "search", "--no-trunc=true", "busybox")
c.Assert(len(outSearchCmd) > len(outSearchCmdNotrunc), check.Equals, false, check.Commentf("The no-trunc option can't take effect.")) c.Assert(len(outSearchCmd) > len(outSearchCmdNotrunc), check.Equals, false, check.Commentf("The no-trunc option can't take effect."))
outSearchCmdautomated, _ := dockerCmd(c, "search", "--automated=true", "busybox") //The busybox is a busybox base image, not an AUTOMATED image. outSearchCmdautomated, _ := dockerCmd(c, "search", "--filter", "is-automated=true", "busybox") //The busybox is a busybox base image, not an AUTOMATED image.
outSearchCmdautomatedSlice := strings.Split(outSearchCmdautomated, "\n") outSearchCmdautomatedSlice := strings.Split(outSearchCmdautomated, "\n")
for i := range outSearchCmdautomatedSlice { for i := range outSearchCmdautomatedSlice {
c.Assert(strings.HasPrefix(outSearchCmdautomatedSlice[i], "busybox "), check.Equals, false, check.Commentf("The busybox is not an AUTOMATED image: %s", out)) c.Assert(strings.HasPrefix(outSearchCmdautomatedSlice[i], "busybox "), check.Equals, false, check.Commentf("The busybox is not an AUTOMATED image: %s", outSearchCmdautomated))
} }
outSearchCmdStars, _ := dockerCmd(c, "search", "-s=2", "busybox") outSearchCmdNotOfficial, _ := dockerCmd(c, "search", "--filter", "is-official=false", "busybox") //The busybox is a busybox base image, official image.
outSearchCmdNotOfficialSlice := strings.Split(outSearchCmdNotOfficial, "\n")
for i := range outSearchCmdNotOfficialSlice {
c.Assert(strings.HasPrefix(outSearchCmdNotOfficialSlice[i], "busybox "), check.Equals, false, check.Commentf("The busybox is not an OFFICIAL image: %s", outSearchCmdNotOfficial))
}
outSearchCmdOfficial, _ := dockerCmd(c, "search", "--filter", "is-official=true", "busybox") //The busybox is a busybox base image, official image.
outSearchCmdOfficialSlice := strings.Split(outSearchCmdOfficial, "\n")
c.Assert(outSearchCmdOfficialSlice, checker.HasLen, 3) // 1 header, 1 line, 1 carriage return
c.Assert(strings.HasPrefix(outSearchCmdOfficialSlice[1], "busybox "), check.Equals, true, check.Commentf("The busybox is an OFFICIAL image: %s", outSearchCmdNotOfficial))
outSearchCmdStars, _ := dockerCmd(c, "search", "--filter", "stars=2", "busybox")
c.Assert(strings.Count(outSearchCmdStars, "[OK]") > strings.Count(outSearchCmd, "[OK]"), check.Equals, false, check.Commentf("The quantity of images with stars should be less than that of all images: %s", outSearchCmdStars)) c.Assert(strings.Count(outSearchCmdStars, "[OK]") > strings.Count(outSearchCmd, "[OK]"), check.Equals, false, check.Commentf("The quantity of images with stars should be less than that of all images: %s", outSearchCmdStars))
dockerCmd(c, "search", "--filter", "is-automated=true", "--filter", "stars=2", "--no-trunc=true", "busybox")
// --automated deprecated since Docker 1.13
outSearchCmdautomated1, _ := dockerCmd(c, "search", "--automated=true", "busybox") //The busybox is a busybox base image, not an AUTOMATED image.
outSearchCmdautomatedSlice1 := strings.Split(outSearchCmdautomated1, "\n")
for i := range outSearchCmdautomatedSlice1 {
c.Assert(strings.HasPrefix(outSearchCmdautomatedSlice1[i], "busybox "), check.Equals, false, check.Commentf("The busybox is not an AUTOMATED image: %s", outSearchCmdautomated))
}
// -s --stars deprecated since Docker 1.13
outSearchCmdStars1, _ := dockerCmd(c, "search", "--stars=2", "busybox")
c.Assert(strings.Count(outSearchCmdStars1, "[OK]") > strings.Count(outSearchCmd, "[OK]"), check.Equals, false, check.Commentf("The quantity of images with stars should be less than that of all images: %s", outSearchCmdStars1))
// -s --stars deprecated since Docker 1.13
dockerCmd(c, "search", "--stars=2", "--automated=true", "--no-trunc=true", "busybox") dockerCmd(c, "search", "--stars=2", "--automated=true", "--no-trunc=true", "busybox")
} }

View file

@ -6,10 +6,9 @@ docker-search - Search the Docker Hub for images
# SYNOPSIS # SYNOPSIS
**docker search** **docker search**
[**--automated**] [**-f**|**--filter**[=*[]*]]
[**--help**] [**--help**]
[**--no-trunc**] [**--no-trunc**]
[**-s**|**--stars**[=*0*]]
TERM TERM
# DESCRIPTION # DESCRIPTION
@ -21,8 +20,12 @@ of stars awarded, whether the image is official, and whether it is automated.
*Note* - Search queries will only return up to 25 results *Note* - Search queries will only return up to 25 results
# OPTIONS # OPTIONS
**--automated**=*true*|*false*
Only show automated builds. The default is *false*. **-f**, **--filter**=[]
Filter output based on these conditions:
- stars=<numberOfStar>
- is-automated=(true|false)
- is-official=(true|false)
**--help** **--help**
Print usage statement Print usage statement
@ -30,9 +33,6 @@ of stars awarded, whether the image is official, and whether it is automated.
**--no-trunc**=*true*|*false* **--no-trunc**=*true*|*false*
Don't truncate output. The default is *false*. Don't truncate output. The default is *false*.
**-s**, **--stars**=*X*
Only displays with at least X stars. The default is zero.
# EXAMPLES # EXAMPLES
## Search Docker Hub for ranked images ## Search Docker Hub for ranked images
@ -40,7 +40,7 @@ of stars awarded, whether the image is official, and whether it is automated.
Search a registry for the term 'fedora' and only display those images Search a registry for the term 'fedora' and only display those images
ranked 3 or higher: ranked 3 or higher:
$ docker search -s 3 fedora $ docker search --filter=stars=3 fedora
NAME DESCRIPTION STARS OFFICIAL AUTOMATED NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mattdm/fedora A basic Fedora image corresponding roughly... 50 mattdm/fedora A basic Fedora image corresponding roughly... 50
fedora (Semi) Official Fedora base image. 38 fedora (Semi) Official Fedora base image. 38
@ -52,7 +52,7 @@ ranked 3 or higher:
Search Docker Hub for the term 'fedora' and only display automated images Search Docker Hub for the term 'fedora' and only display automated images
ranked 1 or higher: ranked 1 or higher:
$ docker search --automated -s 1 fedora $ docker search --filter=is-automated=true --filter=stars=1 fedora
NAME DESCRIPTION STARS OFFICIAL AUTOMATED NAME DESCRIPTION STARS OFFICIAL AUTOMATED
goldmann/wildfly A WildFly application server running on a ... 3 [OK] goldmann/wildfly A WildFly application server running on a ... 3 [OK]
tutum/fedora-20 Fedora 20 image with SSH access. For the r... 1 [OK] tutum/fedora-20 Fedora 20 image with SSH access. For the r... 1 [OK]
@ -62,4 +62,5 @@ April 2014, Originally compiled by William Henry (whenry at redhat dot com)
based on docker.com source material and internal work. based on docker.com source material and internal work.
June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au> June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
April 2015, updated by Mary Anthony for v2 <mary@docker.com> April 2015, updated by Mary Anthony for v2 <mary@docker.com>
April 2016, updated by Vincent Demeester <vincent@sbr.pm>