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:
parent
0e9009bae3
commit
e009ebdf4c
12 changed files with 272 additions and 49 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) \
|
||||||
|
|
|
@ -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 ®istrytypes.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
|
||||||
|
|
|
@ -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**
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue