-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Expand file tree
/
Copy pathsearch.go
More file actions
126 lines (109 loc) · 4.14 KB
/
search.go
File metadata and controls
126 lines (109 loc) · 4.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package registry
import (
"context"
"fmt"
"strings"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/opts"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/spf13/cobra"
)
type searchOptions struct {
format string
term string
noTrunc bool
limit int
filter opts.FilterOpt
}
// NewSearchCommand creates a new `docker search` command
//
// Deprecated: Do not import commands directly. They will be removed in a future release.
func NewSearchCommand(dockerCLI command.Cli) *cobra.Command {
return newSearchCommand(dockerCLI)
}
// newSearchCommand creates a new `docker search` command
func newSearchCommand(dockerCLI command.Cli) *cobra.Command {
options := searchOptions{filter: opts.NewFilterOpt()}
cmd := &cobra.Command{
Use: "search [OPTIONS] TERM",
Short: "Search Docker Hub for images",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
options.term = args[0]
return runSearch(cmd.Context(), dockerCLI, options)
},
Annotations: map[string]string{
"category-top": "10",
},
}
flags := cmd.Flags()
flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output")
flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided")
flags.IntVar(&options.limit, "limit", 0, "Max number of search results")
flags.StringVar(&options.format, "format", "", "Pretty-print search using a Go template")
return cmd
}
func runSearch(ctx context.Context, dockerCli command.Cli, options searchOptions) error {
if options.filter.Value().Contains("is-automated") {
_, _ = fmt.Fprintln(dockerCli.Err(), `WARNING: the "is-automated" filter is deprecated, and searching for "is-automated=true" will not yield any results in future.`)
}
encodedAuth, err := getAuth(dockerCli, options.term)
if err != nil {
return err
}
results, err := dockerCli.Client().ImageSearch(ctx, options.term, registrytypes.SearchOptions{
RegistryAuth: encodedAuth,
PrivilegeFunc: nil,
Filters: options.filter.Value(),
Limit: options.limit,
})
if err != nil {
return err
}
searchCtx := formatter.Context{
Output: dockerCli.Out(),
Format: newFormat(options.format),
Trunc: !options.noTrunc,
}
return formatWrite(searchCtx, results)
}
// authConfigKey is the key used to store credentials for Docker Hub. It is
// a copy of [registry.IndexServer].
//
// [registry.IndexServer]: https://pkg.go.dev/github.com/docker/docker/registry#IndexServer
const authConfigKey = "https://index.docker.io/v1/"
// getAuth will use fetch auth based on the given search-term. If the search
// does not contain a hostname for the registry, it assumes Docker Hub is used,
// and resolves authentication for Docker Hub, otherwise it resolves authentication
// for the given registry.
func getAuth(dockerCLI command.Cli, reposName string) (encodedAuth string, err error) {
authCfgKey := splitReposSearchTerm(reposName)
if authCfgKey == "docker.io" || authCfgKey == "index.docker.io" {
authCfgKey = authConfigKey
}
// Ignoring errors here, which was the existing behavior (likely
// "no credentials found"). We'll get an error when search failed,
// so fine to ignore in most situations.
authConfig, _ := dockerCLI.ConfigFile().GetAuthConfig(authCfgKey)
return registrytypes.EncodeAuthConfig(registrytypes.AuthConfig{
Username: authConfig.Username,
Password: authConfig.Password,
ServerAddress: authConfig.ServerAddress,
// TODO(thaJeztah): Are these expected to be included?
Auth: authConfig.Auth,
IdentityToken: authConfig.IdentityToken,
RegistryToken: authConfig.RegistryToken,
})
}
// splitReposSearchTerm breaks a search term into an index name and remote name
func splitReposSearchTerm(reposName string) string {
nameParts := strings.SplitN(reposName, "/", 2)
if len(nameParts) == 1 || (!strings.Contains(nameParts[0], ".") && !strings.Contains(nameParts[0], ":") && nameParts[0] != "localhost") {
// This is a Docker Hub repository (ex: samalba/hipache or ubuntu),
// use the default Docker Hub registry (docker.io)
return "docker.io"
}
return nameParts[0]
}