github.com/kunnos/engine@v1.13.1/cli/command/registry/search.go (about) 1 package registry 2 3 import ( 4 "fmt" 5 "sort" 6 "strings" 7 "text/tabwriter" 8 9 "golang.org/x/net/context" 10 11 "github.com/docker/docker/api/types" 12 registrytypes "github.com/docker/docker/api/types/registry" 13 "github.com/docker/docker/cli" 14 "github.com/docker/docker/cli/command" 15 "github.com/docker/docker/opts" 16 "github.com/docker/docker/pkg/stringutils" 17 "github.com/docker/docker/registry" 18 "github.com/spf13/cobra" 19 ) 20 21 type searchOptions struct { 22 term string 23 noTrunc bool 24 limit int 25 filter opts.FilterOpt 26 27 // Deprecated 28 stars uint 29 automated bool 30 } 31 32 // NewSearchCommand creates a new `docker search` command 33 func NewSearchCommand(dockerCli *command.DockerCli) *cobra.Command { 34 opts := searchOptions{filter: opts.NewFilterOpt()} 35 36 cmd := &cobra.Command{ 37 Use: "search [OPTIONS] TERM", 38 Short: "Search the Docker Hub for images", 39 Args: cli.ExactArgs(1), 40 RunE: func(cmd *cobra.Command, args []string) error { 41 opts.term = args[0] 42 return runSearch(dockerCli, opts) 43 }, 44 } 45 46 flags := cmd.Flags() 47 48 flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output") 49 flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided") 50 flags.IntVar(&opts.limit, "limit", registry.DefaultSearchLimit, "Max number of search results") 51 52 flags.BoolVar(&opts.automated, "automated", false, "Only show automated builds") 53 flags.UintVarP(&opts.stars, "stars", "s", 0, "Only displays with at least x stars") 54 55 flags.MarkDeprecated("automated", "use --filter=automated=true instead") 56 flags.MarkDeprecated("stars", "use --filter=stars=3 instead") 57 58 return cmd 59 } 60 61 func runSearch(dockerCli *command.DockerCli, opts searchOptions) error { 62 indexInfo, err := registry.ParseSearchIndexInfo(opts.term) 63 if err != nil { 64 return err 65 } 66 67 ctx := context.Background() 68 69 authConfig := command.ResolveAuthConfig(ctx, dockerCli, indexInfo) 70 requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search") 71 72 encodedAuth, err := command.EncodeAuthToBase64(authConfig) 73 if err != nil { 74 return err 75 } 76 77 options := types.ImageSearchOptions{ 78 RegistryAuth: encodedAuth, 79 PrivilegeFunc: requestPrivilege, 80 Filters: opts.filter.Value(), 81 Limit: opts.limit, 82 } 83 84 clnt := dockerCli.Client() 85 86 unorderedResults, err := clnt.ImageSearch(ctx, opts.term, options) 87 if err != nil { 88 return err 89 } 90 91 results := searchResultsByStars(unorderedResults) 92 sort.Sort(results) 93 94 w := tabwriter.NewWriter(dockerCli.Out(), 10, 1, 3, ' ', 0) 95 fmt.Fprintf(w, "NAME\tDESCRIPTION\tSTARS\tOFFICIAL\tAUTOMATED\n") 96 for _, res := range results { 97 // --automated and -s, --stars are deprecated since Docker 1.12 98 if (opts.automated && !res.IsAutomated) || (int(opts.stars) > res.StarCount) { 99 continue 100 } 101 desc := strings.Replace(res.Description, "\n", " ", -1) 102 desc = strings.Replace(desc, "\r", " ", -1) 103 if !opts.noTrunc { 104 desc = stringutils.Ellipsis(desc, 45) 105 } 106 fmt.Fprintf(w, "%s\t%s\t%d\t", res.Name, desc, res.StarCount) 107 if res.IsOfficial { 108 fmt.Fprint(w, "[OK]") 109 110 } 111 fmt.Fprint(w, "\t") 112 if res.IsAutomated { 113 fmt.Fprint(w, "[OK]") 114 } 115 fmt.Fprint(w, "\n") 116 } 117 w.Flush() 118 return nil 119 } 120 121 // SearchResultsByStars sorts search results in descending order by number of stars. 122 type searchResultsByStars []registrytypes.SearchResult 123 124 func (r searchResultsByStars) Len() int { return len(r) } 125 func (r searchResultsByStars) Swap(i, j int) { r[i], r[j] = r[j], r[i] } 126 func (r searchResultsByStars) Less(i, j int) bool { return r[j].StarCount < r[i].StarCount }