119 lines
3.9 KiB
Go
119 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
|
|
"github.com/containers/buildah/pkg/formats"
|
|
"github.com/containers/image/v4/types"
|
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
|
"github.com/containers/libpod/cmd/podman/shared"
|
|
"github.com/containers/libpod/libpod/image"
|
|
"github.com/pkg/errors"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
searchCommand cliconfig.SearchValues
|
|
searchDescription = `Search registries for a given image. Can search all the default registries or a specific registry.
|
|
|
|
Users can limit the number of results, and filter the output based on certain conditions.`
|
|
_searchCommand = &cobra.Command{
|
|
Use: "search [flags] TERM",
|
|
Short: "Search registry for image",
|
|
Long: searchDescription,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
searchCommand.InputArgs = args
|
|
searchCommand.GlobalFlags = MainGlobalOpts
|
|
searchCommand.Remote = remoteclient
|
|
return searchCmd(&searchCommand)
|
|
},
|
|
Example: `podman search --filter=is-official --limit 3 alpine
|
|
podman search registry.fedoraproject.org/ # only works with v2 registries
|
|
podman search --format "table {{.Index}} {{.Name}}" registry.fedoraproject.org/fedora`,
|
|
}
|
|
)
|
|
|
|
func init() {
|
|
searchCommand.Command = _searchCommand
|
|
searchCommand.SetHelpTemplate(HelpTemplate())
|
|
searchCommand.SetUsageTemplate(UsageTemplate())
|
|
flags := searchCommand.Flags()
|
|
flags.StringSliceVarP(&searchCommand.Filter, "filter", "f", []string{}, "Filter output based on conditions provided (default [])")
|
|
flags.StringVar(&searchCommand.Format, "format", "", "Change the output format to a Go template")
|
|
flags.IntVar(&searchCommand.Limit, "limit", 0, "Limit the number of results")
|
|
flags.BoolVar(&searchCommand.NoTrunc, "no-trunc", false, "Do not truncate the output")
|
|
// Disabled flags for the remote client
|
|
if !remote {
|
|
flags.StringVar(&searchCommand.Authfile, "authfile", shared.GetAuthFile(""), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
|
|
flags.BoolVar(&searchCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
|
|
}
|
|
}
|
|
|
|
func searchCmd(c *cliconfig.SearchValues) error {
|
|
args := c.InputArgs
|
|
if len(args) > 1 {
|
|
return errors.Errorf("too many arguments. Requires exactly 1")
|
|
}
|
|
if len(args) == 0 {
|
|
return errors.Errorf("no argument given, requires exactly 1 argument")
|
|
}
|
|
term := args[0]
|
|
|
|
filter, err := image.ParseSearchFilter(c.Filter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
searchOptions := image.SearchOptions{
|
|
NoTrunc: c.NoTrunc,
|
|
Limit: c.Limit,
|
|
Filter: *filter,
|
|
Authfile: c.Authfile,
|
|
}
|
|
if c.Flag("tls-verify").Changed {
|
|
searchOptions.InsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
|
|
}
|
|
|
|
results, err := image.SearchImages(term, searchOptions)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
format := genSearchFormat(c.Format)
|
|
if len(results) == 0 {
|
|
return nil
|
|
}
|
|
out := formats.StdoutTemplateArray{Output: searchToGeneric(results), Template: format, Fields: searchHeaderMap()}
|
|
return out.Out()
|
|
}
|
|
|
|
// searchHeaderMap returns the headers of a SearchResult.
|
|
func searchHeaderMap() map[string]string {
|
|
s := new(image.SearchResult)
|
|
v := reflect.Indirect(reflect.ValueOf(s))
|
|
values := make(map[string]string, v.NumField())
|
|
|
|
for i := 0; i < v.NumField(); i++ {
|
|
key := v.Type().Field(i).Name
|
|
value := key
|
|
values[key] = strings.ToUpper(splitCamelCase(value))
|
|
}
|
|
return values
|
|
}
|
|
|
|
func genSearchFormat(format string) string {
|
|
if format != "" {
|
|
// "\t" from the command line is not being recognized as a tab
|
|
// replacing the string "\t" to a tab character if the user passes in "\t"
|
|
return strings.Replace(format, `\t`, "\t", -1)
|
|
}
|
|
return "table {{.Index}}\t{{.Name}}\t{{.Description}}\t{{.Stars}}\t{{.Official}}\t{{.Automated}}\t"
|
|
}
|
|
|
|
func searchToGeneric(params []image.SearchResult) (genericParams []interface{}) {
|
|
for _, v := range params {
|
|
genericParams = append(genericParams, interface{}(v))
|
|
}
|
|
return genericParams
|
|
}
|