diff options
Diffstat (limited to 'cmd/podman/images')
-rw-r--r-- | cmd/podman/images/diff.go | 12 | ||||
-rw-r--r-- | cmd/podman/images/exists.go | 5 | ||||
-rw-r--r-- | cmd/podman/images/history.go | 22 | ||||
-rw-r--r-- | cmd/podman/images/image.go | 6 | ||||
-rw-r--r-- | cmd/podman/images/images.go | 13 | ||||
-rw-r--r-- | cmd/podman/images/inspect.go | 97 | ||||
-rw-r--r-- | cmd/podman/images/list.go | 87 | ||||
-rw-r--r-- | cmd/podman/images/load.go | 3 | ||||
-rw-r--r-- | cmd/podman/images/prune.go | 3 | ||||
-rw-r--r-- | cmd/podman/images/pull.go | 12 | ||||
-rw-r--r-- | cmd/podman/images/push.go | 14 | ||||
-rw-r--r-- | cmd/podman/images/rm.go | 35 | ||||
-rw-r--r-- | cmd/podman/images/search.go | 27 | ||||
-rw-r--r-- | cmd/podman/images/tree.go | 40 |
14 files changed, 198 insertions, 178 deletions
diff --git a/cmd/podman/images/diff.go b/cmd/podman/images/diff.go index dd98dc4d6..7cfacfc6c 100644 --- a/cmd/podman/images/diff.go +++ b/cmd/podman/images/diff.go @@ -11,8 +11,8 @@ import ( var ( // podman container _inspect_ diffCmd = &cobra.Command{ - Use: "diff [flags] CONTAINER", - Args: registry.IdOrLatestArgs, + Use: "diff [flags] IMAGE", + Args: cobra.ExactArgs(1), Short: "Inspect changes on image's file systems", Long: `Displays changes on a image's filesystem. The image will be compared to its parent layer.`, RunE: diff, @@ -32,16 +32,16 @@ func init() { diffOpts = &entities.DiffOptions{} flags := diffCmd.Flags() flags.BoolVar(&diffOpts.Archive, "archive", true, "Save the diff as a tar archive") - _ = flags.MarkHidden("archive") + _ = flags.MarkDeprecated("archive", "Provided for backwards compatibility, has no impact on output.") flags.StringVar(&diffOpts.Format, "format", "", "Change the output format") } func diff(cmd *cobra.Command, args []string) error { - if len(args) == 0 && !diffOpts.Latest { - return errors.New("image must be specified: podman image diff [options [...]] ID-NAME") + if diffOpts.Latest { + return errors.New("image diff does not support --latest") } - results, err := registry.ImageEngine().Diff(registry.GetContext(), args[0], entities.DiffOptions{}) + results, err := registry.ImageEngine().Diff(registry.GetContext(), args[0], *diffOpts) if err != nil { return err } diff --git a/cmd/podman/images/exists.go b/cmd/podman/images/exists.go index 0bb288b96..13191113f 100644 --- a/cmd/podman/images/exists.go +++ b/cmd/podman/images/exists.go @@ -1,8 +1,6 @@ package images import ( - "os" - "github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/pkg/domain/entities" "github.com/spf13/cobra" @@ -17,6 +15,7 @@ var ( RunE: exists, Example: `podman image exists ID podman image exists IMAGE && podman pull IMAGE`, + DisableFlagsInUseLine: true, } ) @@ -34,7 +33,7 @@ func exists(cmd *cobra.Command, args []string) error { return err } if !found.Value { - os.Exit(1) + registry.SetExitCode(1) } return nil } diff --git a/cmd/podman/images/history.go b/cmd/podman/images/history.go index c92072bff..ce153aa46 100644 --- a/cmd/podman/images/history.go +++ b/cmd/podman/images/history.go @@ -13,7 +13,6 @@ import ( "github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/pkg/domain/entities" "github.com/docker/go-units" - jsoniter "github.com/json-iterator/go" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -77,7 +76,6 @@ func history(cmd *cobra.Command, args []string) error { layers[i].ImageHistoryLayer = l layers[i].Created = l.Created.Format(time.RFC3339) } - json := jsoniter.ConfigCompatibleWithStandardLibrary enc := json.NewEncoder(os.Stdout) err = enc.Encode(layers) } @@ -91,22 +89,20 @@ func history(cmd *cobra.Command, args []string) error { hdr := "ID\tCREATED\tCREATED BY\tSIZE\tCOMMENT\n" row := "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n" - if len(opts.format) > 0 { + switch { + case len(opts.format) > 0: hdr = "" row = opts.format if !strings.HasSuffix(opts.format, "\n") { row += "\n" } - } else { - switch { - case opts.human: - row = "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n" - case opts.noTrunc: - row = "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n" - case opts.quiet: - hdr = "" - row = "{{.ID}}\n" - } + case opts.quiet: + hdr = "" + row = "{{.ID}}\n" + case opts.human: + row = "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n" + case opts.noTrunc: + row = "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n" } format := hdr + "{{range . }}" + row + "{{end}}" diff --git a/cmd/podman/images/image.go b/cmd/podman/images/image.go index 37e46ab9e..790c16c05 100644 --- a/cmd/podman/images/image.go +++ b/cmd/podman/images/image.go @@ -2,18 +2,22 @@ package images import ( "github.com/containers/libpod/cmd/podman/registry" + "github.com/containers/libpod/cmd/podman/validate" "github.com/containers/libpod/pkg/domain/entities" "github.com/spf13/cobra" ) var ( + // Pull in configured json library + json = registry.JsonLibrary() + // Command: podman _image_ imageCmd = &cobra.Command{ Use: "image", Short: "Manage images", Long: "Manage images", TraverseChildren: true, - RunE: registry.SubCommandExists, + RunE: validate.SubCommandExists, } ) diff --git a/cmd/podman/images/images.go b/cmd/podman/images/images.go index fd3ede26a..96ef344bf 100644 --- a/cmd/podman/images/images.go +++ b/cmd/podman/images/images.go @@ -11,12 +11,13 @@ import ( var ( // podman _images_ Alias for podman image _list_ imagesCmd = &cobra.Command{ - Use: strings.Replace(listCmd.Use, "list", "images", 1), - Args: listCmd.Args, - Short: listCmd.Short, - Long: listCmd.Long, - RunE: listCmd.RunE, - Example: strings.Replace(listCmd.Example, "podman image list", "podman images", -1), + Use: strings.Replace(listCmd.Use, "list", "images", 1), + Args: listCmd.Args, + Short: listCmd.Short, + Long: listCmd.Long, + RunE: listCmd.RunE, + Example: strings.Replace(listCmd.Example, "podman image list", "podman images", -1), + DisableFlagsInUseLine: true, } ) diff --git a/cmd/podman/images/inspect.go b/cmd/podman/images/inspect.go index 4482ceee5..8c727eb07 100644 --- a/cmd/podman/images/inspect.go +++ b/cmd/podman/images/inspect.go @@ -1,30 +1,22 @@ package images import ( - "context" - "encoding/json" - "fmt" - "os" - "strings" - "text/tabwriter" - "text/template" - - "github.com/containers/buildah/pkg/formats" - "github.com/containers/libpod/cmd/podman/common" + "github.com/containers/libpod/cmd/podman/inspect" "github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" "github.com/spf13/cobra" ) var ( // Command: podman image _inspect_ inspectCmd = &cobra.Command{ - Use: "inspect [flags] IMAGE", - Short: "Display the configuration of an image", - Long: `Displays the low-level information on an image identified by name or ID.`, - RunE: inspect, - Example: `podman image inspect alpine`, + Use: "inspect [flags] IMAGE", + Short: "Display the configuration of an image", + Long: `Displays the low-level information of an image identified by name or ID.`, + RunE: inspectExec, + Example: `podman inspect alpine + podman inspect --format "imageId: {{.Id}} size: {{.Size}}" alpine + podman inspect --format "image: {{.ImageName}} driver: {{.Driver}}" myctr`, } inspectOpts *entities.InspectOptions ) @@ -35,74 +27,11 @@ func init() { Command: inspectCmd, Parent: imageCmd, }) - inspectOpts = common.AddInspectFlagSet(inspectCmd) -} - -func inspect(cmd *cobra.Command, args []string) error { - latestContainer := inspectOpts.Latest - - if len(args) == 0 && !latestContainer { - return errors.Errorf("container or image name must be specified: podman inspect [options [...]] name") - } - - if len(args) > 0 && latestContainer { - return errors.Errorf("you cannot provide additional arguments with --latest") - } - - results, err := registry.ImageEngine().Inspect(context.Background(), args, *inspectOpts) - if err != nil { - return err - } - - if len(results.Images) > 0 { - if inspectOpts.Format == "" { - buf, err := json.MarshalIndent(results.Images, "", " ") - if err != nil { - return err - } - fmt.Println(string(buf)) - - for id, e := range results.Errors { - fmt.Fprintf(os.Stderr, "%s: %s\n", id, e.Error()) - } - return nil - } - row := inspectFormat(inspectOpts.Format) - format := "{{range . }}" + row + "{{end}}" - tmpl, err := template.New("inspect").Parse(format) - if err != nil { - return err - } - - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) - defer func() { _ = w.Flush() }() - err = tmpl.Execute(w, results.Images) - if err != nil { - return err - } - } - - for id, e := range results.Errors { - fmt.Fprintf(os.Stderr, "%s: %s\n", id, e.Error()) - } - return nil -} - -func inspectFormat(row string) string { - r := strings.NewReplacer("{{.Id}}", formats.IDString, - ".Src", ".Source", - ".Dst", ".Destination", - ".ImageID", ".Image", - ) - row = r.Replace(row) - - if !strings.HasSuffix(row, "\n") { - row += "\n" - } - return row + inspectOpts = inspect.AddInspectFlagSet(inspectCmd) + flags := inspectCmd.Flags() + _ = flags.MarkHidden("latest") // Shared with container-inspect but not wanted here. } -func Inspect(cmd *cobra.Command, args []string, options *entities.InspectOptions) error { - inspectOpts = options - return inspect(cmd, args) +func inspectExec(cmd *cobra.Command, args []string) error { + return inspect.Inspect(args, *inspectOpts) } diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go index 366dfc4ba..83c039ed3 100644 --- a/cmd/podman/images/list.go +++ b/cmd/podman/images/list.go @@ -14,7 +14,6 @@ import ( "github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/pkg/domain/entities" "github.com/docker/go-units" - jsoniter "github.com/json-iterator/go" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -33,7 +32,7 @@ type listFlagType struct { var ( // Command: podman image _list_ listCmd = &cobra.Command{ - Use: "list [flag] [IMAGE]", + Use: "list [FLAGS] [IMAGE]", Aliases: []string{"ls"}, Args: cobra.MaximumNArgs(1), Short: "List images in local storage", @@ -42,6 +41,7 @@ var ( Example: `podman image list --format json podman image list --sort repository --format "table {{.ID}} {{.Repository}} {{.Tag}}" podman image list --filter dangling=true`, + DisableFlagsInUseLine: true, } // Options to pull data @@ -99,38 +99,54 @@ func images(cmd *cobra.Command, args []string) error { return err } - imageS := summaries - sort.Slice(imageS, sortFunc(listFlag.sort, imageS)) + switch { + case listFlag.quiet: + return writeId(summaries) + case cmd.Flag("format").Changed && listFlag.format == "json": + return writeJSON(summaries) + default: + return writeTemplate(summaries) + } +} - if cmd.Flag("format").Changed && listFlag.format == "json" { - return writeJSON(imageS) - } else { - return writeTemplate(imageS, err) +func writeId(imageS []*entities.ImageSummary) error { + var ids = map[string]struct{}{} + for _, e := range imageS { + i := "sha256:" + e.ID + if !listFlag.noTrunc { + i = fmt.Sprintf("%12.12s", e.ID) + } + ids[i] = struct{}{} } + for k := range ids { + fmt.Fprint(os.Stdout, k+"\n") + } + return nil } func writeJSON(imageS []*entities.ImageSummary) error { type image struct { entities.ImageSummary - Created string + Created string + CreatedAt string } imgs := make([]image, 0, len(imageS)) for _, e := range imageS { var h image h.ImageSummary = *e - h.Created = time.Unix(e.Created, 0).Format(time.RFC3339) + h.Created = units.HumanDuration(time.Since(e.Created)) + " ago" + h.CreatedAt = e.Created.Format(time.RFC3339Nano) h.RepoTags = nil imgs = append(imgs, h) } - json := jsoniter.ConfigCompatibleWithStandardLibrary enc := json.NewEncoder(os.Stdout) return enc.Encode(imgs) } -func writeTemplate(imageS []*entities.ImageSummary, err error) error { +func writeTemplate(imageS []*entities.ImageSummary) error { var ( hdr, row string ) @@ -142,10 +158,11 @@ func writeTemplate(imageS []*entities.ImageSummary, err error) error { h.Repository, h.Tag = tokenRepoTag(tag) imgs = append(imgs, h) } - if e.IsReadOnly() { - listFlag.readOnly = true - } + listFlag.readOnly = e.IsReadOnly() } + + sort.Slice(imgs, sortFunc(listFlag.sort, imgs)) + if len(listFlag.format) < 1 { hdr, row = imageListFormat(listFlag) } else { @@ -175,37 +192,33 @@ func tokenRepoTag(tag string) (string, string) { } } -func sortFunc(key string, data []*entities.ImageSummary) func(i, j int) bool { +func sortFunc(key string, data []imageReporter) func(i, j int) bool { switch key { case "id": return func(i, j int) bool { - return data[i].ID < data[j].ID + return data[i].ID() < data[j].ID() } case "repository": return func(i, j int) bool { - return data[i].RepoTags[0] < data[j].RepoTags[0] + return data[i].Repository < data[j].Repository } case "size": return func(i, j int) bool { - return data[i].Size < data[j].Size + return data[i].size() < data[j].size() } case "tag": return func(i, j int) bool { - return data[i].RepoTags[0] < data[j].RepoTags[0] + return data[i].Tag < data[j].Tag } default: // case "created": return func(i, j int) bool { - return data[i].Created >= data[j].Created + return data[i].created().After(data[j].created()) } } } func imageListFormat(flags listFlagType) (string, string) { - if flags.quiet { - return "", "{{.ID}}\n" - } - // Defaults hdr := "REPOSITORY\tTAG" row := "{{.Repository}}\t{{if .Tag}}{{.Tag}}{{else}}<none>{{end}}" @@ -255,11 +268,15 @@ func (i imageReporter) ID() string { if !listFlag.noTrunc && len(i.ImageSummary.ID) >= 12 { return i.ImageSummary.ID[0:12] } - return i.ImageSummary.ID + return "sha256:" + i.ImageSummary.ID } func (i imageReporter) Created() string { - return units.HumanDuration(time.Since(time.Unix(i.ImageSummary.Created, 0))) + " ago" + return units.HumanDuration(time.Since(i.ImageSummary.Created)) + " ago" +} + +func (i imageReporter) created() time.Time { + return i.ImageSummary.Created } func (i imageReporter) Size() string { @@ -271,3 +288,19 @@ func (i imageReporter) Size() string { func (i imageReporter) History() string { return strings.Join(i.ImageSummary.History, ", ") } + +func (i imageReporter) CreatedAt() string { + return i.ImageSummary.Created.String() +} + +func (i imageReporter) CreatedSince() string { + return i.Created() +} + +func (i imageReporter) CreatedTime() string { + return i.CreatedAt() +} + +func (i imageReporter) size() int64 { + return i.ImageSummary.Size +} diff --git a/cmd/podman/images/load.go b/cmd/podman/images/load.go index 23c657b59..f49f95002 100644 --- a/cmd/podman/images/load.go +++ b/cmd/podman/images/load.go @@ -6,6 +6,7 @@ import ( "io" "io/ioutil" "os" + "strings" "github.com/containers/image/v5/docker/reference" "github.com/containers/libpod/cmd/podman/parse" @@ -89,6 +90,6 @@ func load(cmd *cobra.Command, args []string) error { if err != nil { return err } - fmt.Println("Loaded image: " + response.Name) + fmt.Println("Loaded image(s): " + strings.Join(response.Names, ",")) return nil } diff --git a/cmd/podman/images/prune.go b/cmd/podman/images/prune.go index b90d889be..53a1966c1 100644 --- a/cmd/podman/images/prune.go +++ b/cmd/podman/images/prune.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/containers/libpod/cmd/podman/registry" + "github.com/containers/libpod/cmd/podman/validate" "github.com/containers/libpod/pkg/domain/entities" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -18,7 +19,7 @@ var ( If an image is not being used by a container, it will be removed from the system.` pruneCmd = &cobra.Command{ Use: "prune", - Args: cobra.NoArgs, + Args: validate.NoArgs, Short: "Remove unused images", Long: pruneDescription, RunE: prune, diff --git a/cmd/podman/images/pull.go b/cmd/podman/images/pull.go index fb107d00c..fead5f7ed 100644 --- a/cmd/podman/images/pull.go +++ b/cmd/podman/images/pull.go @@ -2,11 +2,13 @@ package images import ( "fmt" + "os" buildahcli "github.com/containers/buildah/pkg/cli" "github.com/containers/image/v5/types" "github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/pkg/domain/entities" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -91,18 +93,22 @@ func pullFlags(flags *pflag.FlagSet) { // imagePull is implement the command for pulling images. func imagePull(cmd *cobra.Command, args []string) error { - pullOptsAPI := pullOptions.ImagePullOptions // TLS verification in c/image is controlled via a `types.OptionalBool` // which allows for distinguishing among set-true, set-false, unspecified // which is important to implement a sane way of dealing with defaults of // boolean CLI flags. if cmd.Flags().Changed("tls-verify") { - pullOptsAPI.TLSVerify = types.NewOptionalBool(pullOptions.TLSVerifyCLI) + pullOptions.SkipTLSVerify = types.NewOptionalBool(!pullOptions.TLSVerifyCLI) + } + if pullOptions.Authfile != "" { + if _, err := os.Stat(pullOptions.Authfile); err != nil { + return errors.Wrapf(err, "error getting authfile %s", pullOptions.Authfile) + } } // Let's do all the remaining Yoga in the API to prevent us from // scattering logic across (too) many parts of the code. - pullReport, err := registry.ImageEngine().Pull(registry.GetContext(), args[0], pullOptsAPI) + pullReport, err := registry.ImageEngine().Pull(registry.GetContext(), args[0], pullOptions.ImagePullOptions) if err != nil { return err } diff --git a/cmd/podman/images/push.go b/cmd/podman/images/push.go index f12a5ac86..0b3502d61 100644 --- a/cmd/podman/images/push.go +++ b/cmd/podman/images/push.go @@ -1,6 +1,8 @@ package images import ( + "os" + buildahcli "github.com/containers/buildah/pkg/cli" "github.com/containers/image/v5/types" "github.com/containers/libpod/cmd/podman/registry" @@ -96,6 +98,7 @@ func imagePush(cmd *cobra.Command, args []string) error { switch len(args) { case 1: source = args[0] + destination = args[0] case 2: source = args[0] destination = args[1] @@ -105,16 +108,21 @@ func imagePush(cmd *cobra.Command, args []string) error { return errors.New("push requires at least one image name, or optionally a second to specify a different destination") } - pushOptsAPI := pushOptions.ImagePushOptions // TLS verification in c/image is controlled via a `types.OptionalBool` // which allows for distinguishing among set-true, set-false, unspecified // which is important to implement a sane way of dealing with defaults of // boolean CLI flags. if cmd.Flags().Changed("tls-verify") { - pushOptsAPI.TLSVerify = types.NewOptionalBool(pushOptions.TLSVerifyCLI) + pushOptions.SkipTLSVerify = types.NewOptionalBool(!pushOptions.TLSVerifyCLI) + } + + if pushOptions.Authfile != "" { + if _, err := os.Stat(pushOptions.Authfile); err != nil { + return errors.Wrapf(err, "error getting authfile %s", pushOptions.Authfile) + } } // Let's do all the remaining Yoga in the API to prevent us from scattering // logic across (too) many parts of the code. - return registry.ImageEngine().Push(registry.GetContext(), source, destination, pushOptsAPI) + return registry.ImageEngine().Push(registry.GetContext(), source, destination, pushOptions.ImagePushOptions) } diff --git a/cmd/podman/images/rm.go b/cmd/podman/images/rm.go index 135fda387..1cf5fa365 100644 --- a/cmd/podman/images/rm.go +++ b/cmd/podman/images/rm.go @@ -2,7 +2,6 @@ package images import ( "fmt" - "os" "github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/pkg/domain/entities" @@ -23,7 +22,7 @@ var ( podman image rm c4dfb1609ee2 93fd78260bd1 c0ed59d05ff7`, } - imageOpts = entities.ImageDeleteOptions{} + imageOpts = entities.ImageRemoveOptions{} ) func init() { @@ -40,32 +39,28 @@ func imageRemoveFlagSet(flags *pflag.FlagSet) { flags.BoolVarP(&imageOpts.All, "all", "a", false, "Remove all images") flags.BoolVarP(&imageOpts.Force, "force", "f", false, "Force Removal of the image") } -func rm(cmd *cobra.Command, args []string) error { +func rm(cmd *cobra.Command, args []string) error { if len(args) < 1 && !imageOpts.All { return errors.Errorf("image name or ID must be specified") } if len(args) > 0 && imageOpts.All { return errors.Errorf("when using the --all switch, you may not pass any images names or IDs") } - report, err := registry.ImageEngine().Delete(registry.GetContext(), args, imageOpts) - if err != nil { - switch { - case report != nil && report.ImageNotFound != nil: - fmt.Fprintln(os.Stderr, err.Error()) - registry.SetExitCode(2) - case report != nil && report.ImageInUse != nil: - fmt.Fprintln(os.Stderr, err.Error()) - default: - return err + + report, err := registry.ImageEngine().Remove(registry.GetContext(), args, imageOpts) + if report != nil { + for _, u := range report.Untagged { + fmt.Println("Untagged: " + u) } + for _, d := range report.Deleted { + // Make sure an image was deleted (and not just untagged); else print it + if len(d) > 0 { + fmt.Println("Deleted: " + d) + } + } + registry.SetExitCode(report.ExitCode) } - for _, u := range report.Untagged { - fmt.Println("Untagged: " + u) - } - for _, d := range report.Deleted { - fmt.Println("Deleted: " + d) - } - return nil + return err } diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go index fdad94d45..a8abfb339 100644 --- a/cmd/podman/images/search.go +++ b/cmd/podman/images/search.go @@ -1,6 +1,7 @@ package images import ( + "os" "reflect" "strings" @@ -47,14 +48,15 @@ var ( // Command: podman image search imageSearchCmd = &cobra.Command{ - Use: searchCmd.Use, - Short: searchCmd.Short, - Long: searchCmd.Long, - RunE: searchCmd.RunE, - Args: searchCmd.Args, + Use: searchCmd.Use, + Short: searchCmd.Short, + Long: searchCmd.Long, + RunE: searchCmd.RunE, + Args: searchCmd.Args, + Annotations: searchCmd.Annotations, Example: `podman image search --filter=is-official --limit 3 alpine - podman image search registry.fedoraproject.org/ # only works with v2 registries - podman image search --format "table {{.Index}} {{.Name}}" registry.fedoraproject.org/fedora`, + podman image search registry.fedoraproject.org/ # only works with v2 registries + podman image search --format "table {{.Index}} {{.Name}}" registry.fedoraproject.org/fedora`, } ) @@ -103,16 +105,21 @@ func imageSearch(cmd *cobra.Command, args []string) error { return errors.Errorf("search requires exactly one argument") } - sarchOptsAPI := searchOptions.ImageSearchOptions // TLS verification in c/image is controlled via a `types.OptionalBool` // which allows for distinguishing among set-true, set-false, unspecified // which is important to implement a sane way of dealing with defaults of // boolean CLI flags. if cmd.Flags().Changed("tls-verify") { - sarchOptsAPI.TLSVerify = types.NewOptionalBool(pullOptions.TLSVerifyCLI) + searchOptions.SkipTLSVerify = types.NewOptionalBool(!searchOptions.TLSVerifyCLI) } - searchReport, err := registry.ImageEngine().Search(registry.GetContext(), searchTerm, sarchOptsAPI) + if searchOptions.Authfile != "" { + if _, err := os.Stat(searchOptions.Authfile); err != nil { + return errors.Wrapf(err, "error getting authfile %s", searchOptions.Authfile) + } + } + + searchReport, err := registry.ImageEngine().Search(registry.GetContext(), searchTerm, searchOptions.ImageSearchOptions) if err != nil { return err } diff --git a/cmd/podman/images/tree.go b/cmd/podman/images/tree.go new file mode 100644 index 000000000..5e82e9dea --- /dev/null +++ b/cmd/podman/images/tree.go @@ -0,0 +1,40 @@ +package images + +import ( + "fmt" + + "github.com/containers/libpod/cmd/podman/registry" + "github.com/containers/libpod/pkg/domain/entities" + "github.com/spf13/cobra" +) + +var ( + treeDescription = "Prints layer hierarchy of an image in a tree format" + treeCmd = &cobra.Command{ + Use: "tree [flags] IMAGE", + Args: cobra.ExactArgs(1), + Short: treeDescription, + Long: treeDescription, + RunE: tree, + Example: "podman image tree alpine:latest", + } + treeOpts entities.ImageTreeOptions +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: treeCmd, + Parent: imageCmd, + }) + treeCmd.Flags().BoolVar(&treeOpts.WhatRequires, "whatrequires", false, "Show all child images and layers of the specified image") +} + +func tree(_ *cobra.Command, args []string) error { + results, err := registry.ImageEngine().Tree(registry.Context(), args[0], treeOpts) + if err != nil { + return err + } + fmt.Println(results.Tree) + return nil +} |