diff options
Diffstat (limited to 'cmd/podmanV2/images')
-rw-r--r-- | cmd/podmanV2/images/exists.go | 40 | ||||
-rw-r--r-- | cmd/podmanV2/images/history.go | 123 | ||||
-rw-r--r-- | cmd/podmanV2/images/image.go | 35 | ||||
-rw-r--r-- | cmd/podmanV2/images/images.go | 33 | ||||
-rw-r--r-- | cmd/podmanV2/images/inspect.go | 124 | ||||
-rw-r--r-- | cmd/podmanV2/images/list.go | 243 | ||||
-rw-r--r-- | cmd/podmanV2/images/prune.go | 86 | ||||
-rw-r--r-- | cmd/podmanV2/images/rm.go | 70 | ||||
-rw-r--r-- | cmd/podmanV2/images/rmi.go | 30 |
9 files changed, 784 insertions, 0 deletions
diff --git a/cmd/podmanV2/images/exists.go b/cmd/podmanV2/images/exists.go new file mode 100644 index 000000000..d35d6825e --- /dev/null +++ b/cmd/podmanV2/images/exists.go @@ -0,0 +1,40 @@ +package images + +import ( + "os" + + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/pkg/domain/entities" + "github.com/spf13/cobra" +) + +var ( + existsCmd = &cobra.Command{ + Use: "exists IMAGE", + Short: "Check if an image exists in local storage", + Long: `If the named image exists in local storage, podman image exists exits with 0, otherwise the exit code will be 1.`, + Args: cobra.ExactArgs(1), + RunE: exists, + Example: `podman image exists ID + podman image exists IMAGE && podman pull IMAGE`, + } +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: existsCmd, + Parent: imageCmd, + }) +} + +func exists(cmd *cobra.Command, args []string) error { + found, err := registry.ImageEngine().Exists(registry.GetContext(), args[0]) + if err != nil { + return err + } + if !found.Value { + os.Exit(1) + } + return nil +} diff --git a/cmd/podmanV2/images/history.go b/cmd/podmanV2/images/history.go new file mode 100644 index 000000000..f6f15e2f2 --- /dev/null +++ b/cmd/podmanV2/images/history.go @@ -0,0 +1,123 @@ +package images + +import ( + "context" + "fmt" + "os" + "strings" + "text/tabwriter" + "text/template" + "time" + + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/cmd/podmanV2/report" + "github.com/containers/libpod/pkg/domain/entities" + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + long = `Displays the history of an image. + + The information can be printed out in an easy to read, or user specified format, and can be truncated.` + + // podman _history_ + historyCmd = &cobra.Command{ + Use: "history [flags] IMAGE", + Short: "Show history of a specified image", + Long: long, + Example: "podman history quay.io/fedora/fedora", + Args: cobra.ExactArgs(1), + PersistentPreRunE: preRunE, + RunE: history, + } + + opts = struct { + human bool + noTrunc bool + quiet bool + format string + }{} +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: historyCmd, + }) + + historyCmd.SetHelpTemplate(registry.HelpTemplate()) + historyCmd.SetUsageTemplate(registry.UsageTemplate()) + + flags := historyCmd.Flags() + flags.StringVar(&opts.format, "format", "", "Change the output to JSON or a Go template") + flags.BoolVarP(&opts.human, "human", "H", false, "Display sizes and dates in human readable format") + flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate the output") + flags.BoolVar(&opts.noTrunc, "notruncate", false, "Do not truncate the output") + flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Display the numeric IDs only") +} + +func history(cmd *cobra.Command, args []string) error { + results, err := registry.ImageEngine().History(context.Background(), args[0], entities.ImageHistoryOptions{}) + if err != nil { + return err + } + + if opts.format == "json" { + var err error + if len(results.Layers) == 0 { + _, err = fmt.Fprintf(os.Stdout, "[]\n") + } else { + // ah-hoc change to "Created": type and format + type layer struct { + entities.ImageHistoryLayer + Created string `json:"Created"` + } + + layers := make([]layer, len(results.Layers)) + for i, l := range results.Layers { + layers[i].ImageHistoryLayer = l + layers[i].Created = time.Unix(l.Created, 0).Format(time.RFC3339) + } + json := jsoniter.ConfigCompatibleWithStandardLibrary + enc := json.NewEncoder(os.Stdout) + err = enc.Encode(layers) + } + return err + } + + // Defaults + hdr := "ID\tCREATED\tCREATED BY\tSIZE\tCOMMENT\n" + row := "{{slice .ID 0 12}}\t{{humanDuration .Created}}\t{{ellipsis .CreatedBy 45}}\t{{.Size}}\t{{.Comment}}\n" + + if len(opts.format) > 0 { + hdr = "" + row = opts.format + if !strings.HasSuffix(opts.format, "\n") { + row += "\n" + } + } else { + switch { + case opts.human: + row = "{{slice .ID 0 12}}\t{{humanDuration .Created}}\t{{ellipsis .CreatedBy 45}}\t{{humanSize .Size}}\t{{.Comment}}\n" + case opts.noTrunc: + row = "{{.ID}}\t{{humanDuration .Created}}\t{{.CreatedBy}}\t{{humanSize .Size}}\t{{.Comment}}\n" + case opts.quiet: + hdr = "" + row = "{{.ID}}\n" + } + } + format := hdr + "{{range . }}" + row + "{{end}}" + + tmpl := template.Must(template.New("report").Funcs(report.PodmanTemplateFuncs()).Parse(format)) + w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) + + _, _ = w.Write(report.ReportHeader("id", "created", "created by", "size", "comment")) + err = tmpl.Execute(w, results.Layers) + if err != nil { + fmt.Fprintln(os.Stderr, errors.Wrapf(err, "Failed to print report")) + } + w.Flush() + return nil +} diff --git a/cmd/podmanV2/images/image.go b/cmd/podmanV2/images/image.go new file mode 100644 index 000000000..9fc7b21d1 --- /dev/null +++ b/cmd/podmanV2/images/image.go @@ -0,0 +1,35 @@ +package images + +import ( + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/pkg/domain/entities" + "github.com/spf13/cobra" +) + +var ( + // Command: podman _image_ + imageCmd = &cobra.Command{ + Use: "image", + Short: "Manage images", + Long: "Manage images", + TraverseChildren: true, + PersistentPreRunE: preRunE, + RunE: registry.SubCommandExists, + } +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: imageCmd, + }) + imageCmd.SetHelpTemplate(registry.HelpTemplate()) + imageCmd.SetUsageTemplate(registry.UsageTemplate()) +} + +func preRunE(cmd *cobra.Command, args []string) error { + if _, err := registry.NewImageEngine(cmd, args); err != nil { + return err + } + return nil +} diff --git a/cmd/podmanV2/images/images.go b/cmd/podmanV2/images/images.go new file mode 100644 index 000000000..d00f0996e --- /dev/null +++ b/cmd/podmanV2/images/images.go @@ -0,0 +1,33 @@ +package images + +import ( + "strings" + + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/pkg/domain/entities" + "github.com/spf13/cobra" +) + +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, + PreRunE: preRunE, + RunE: listCmd.RunE, + Example: strings.Replace(listCmd.Example, "podman image list", "podman images", -1), + } +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: imagesCmd, + }) + imagesCmd.SetHelpTemplate(registry.HelpTemplate()) + imagesCmd.SetUsageTemplate(registry.UsageTemplate()) + + imageListFlagSet(imagesCmd.Flags()) +} diff --git a/cmd/podmanV2/images/inspect.go b/cmd/podmanV2/images/inspect.go new file mode 100644 index 000000000..f8fd44571 --- /dev/null +++ b/cmd/podmanV2/images/inspect.go @@ -0,0 +1,124 @@ +package images + +import ( + "strings" + + "github.com/containers/buildah/pkg/formats" + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/pkg/domain/entities" + "github.com/containers/libpod/pkg/util" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + inspectOpts = entities.ImageInspectOptions{} + + // 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.`, + PreRunE: populateEngines, + RunE: imageInspect, + Example: `podman image inspect alpine`, + } + + containerEngine entities.ContainerEngine +) + +// Inspect is unique in that it needs both an ImageEngine and a ContainerEngine +func populateEngines(cmd *cobra.Command, args []string) (err error) { + // Populate registry.ImageEngine + err = preRunE(cmd, args) + if err != nil { + return + } + + // Populate registry.ContainerEngine + containerEngine, err = registry.NewContainerEngine(cmd, args) + return +} + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: inspectCmd, + Parent: imageCmd, + }) + + flags := inspectCmd.Flags() + flags.BoolVarP(&inspectOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") + flags.BoolVarP(&inspectOpts.Size, "size", "s", false, "Display total file size") + flags.StringVarP(&inspectOpts.Format, "format", "f", "", "Change the output format to a Go template") + + if registry.EngineOptions.EngineMode == entities.ABIMode { + // TODO: This is the same as V1. We could skip creating the flag altogether in V2... + _ = flags.MarkHidden("latest") + } +} + +const ( + inspectTypeContainer = "container" + inspectTypeImage = "image" + inspectAll = "all" +) + +func imageInspect(cmd *cobra.Command, args []string) error { + inspectType := inspectTypeImage + 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") + } + + if !util.StringInSlice(inspectType, []string{inspectTypeContainer, inspectTypeImage, inspectAll}) { + return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll) + } + + outputFormat := inspectOpts.Format + if strings.Contains(outputFormat, "{{.Id}}") { + outputFormat = strings.Replace(outputFormat, "{{.Id}}", formats.IDString, -1) + } + // These fields were renamed, so we need to provide backward compat for + // the old names. + if strings.Contains(outputFormat, ".Src") { + outputFormat = strings.Replace(outputFormat, ".Src", ".Source", -1) + } + if strings.Contains(outputFormat, ".Dst") { + outputFormat = strings.Replace(outputFormat, ".Dst", ".Destination", -1) + } + if strings.Contains(outputFormat, ".ImageID") { + outputFormat = strings.Replace(outputFormat, ".ImageID", ".Image", -1) + } + _ = outputFormat + // if latestContainer { + // lc, err := ctnrRuntime.GetLatestContainer() + // if err != nil { + // return err + // } + // args = append(args, lc.ID()) + // inspectType = inspectTypeContainer + // } + + // inspectedObjects, iterateErr := iterateInput(getContext(), c.Size, args, runtime, inspectType) + // if iterateErr != nil { + // return iterateErr + // } + // + // var out formats.Writer + // if outputFormat != "" && outputFormat != formats.JSONString { + // // template + // out = formats.StdoutTemplateArray{Output: inspectedObjects, Template: outputFormat} + // } else { + // // default is json output + // out = formats.JSONStructArray{Output: inspectedObjects} + // } + // + // return out.Out() + return nil +} diff --git a/cmd/podmanV2/images/list.go b/cmd/podmanV2/images/list.go new file mode 100644 index 000000000..9a5b47299 --- /dev/null +++ b/cmd/podmanV2/images/list.go @@ -0,0 +1,243 @@ +package images + +import ( + "errors" + "fmt" + "os" + "sort" + "strings" + "text/tabwriter" + "text/template" + "time" + + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/cmd/podmanV2/report" + "github.com/containers/libpod/pkg/domain/entities" + jsoniter "github.com/json-iterator/go" + "github.com/spf13/cobra" + "github.com/spf13/pflag" +) + +type listFlagType struct { + format string + history bool + noHeading bool + noTrunc bool + quiet bool + sort string + readOnly bool + digests bool +} + +var ( + // Command: podman image _list_ + listCmd = &cobra.Command{ + Use: "list [flag] [IMAGE]", + Aliases: []string{"ls"}, + Args: cobra.MaximumNArgs(1), + Short: "List images in local storage", + Long: "Lists images previously pulled to the system or created on the system.", + RunE: images, + Example: `podman image list --format json + podman image list --sort repository --format "table {{.ID}} {{.Repository}} {{.Tag}}" + podman image list --filter dangling=true`, + } + + // Options to pull data + listOptions = entities.ImageListOptions{} + + // Options for presenting data + listFlag = listFlagType{} + + sortFields = entities.NewStringSet( + "created", + "id", + "repository", + "size", + "tag") +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: listCmd, + Parent: imageCmd, + }) + imageListFlagSet(listCmd.Flags()) +} + +func imageListFlagSet(flags *pflag.FlagSet) { + flags.BoolVarP(&listOptions.All, "all", "a", false, "Show all images (default hides intermediate images)") + flags.StringSliceVarP(&listOptions.Filter, "filter", "f", []string{}, "Filter output based on conditions provided (default [])") + flags.StringVar(&listFlag.format, "format", "", "Change the output format to JSON or a Go template") + flags.BoolVar(&listFlag.digests, "digests", false, "Show digests") + flags.BoolVarP(&listFlag.noHeading, "noheading", "n", false, "Do not print column headings") + flags.BoolVar(&listFlag.noTrunc, "no-trunc", false, "Do not truncate output") + flags.BoolVar(&listFlag.noTrunc, "notruncate", false, "Do not truncate output") + flags.BoolVarP(&listFlag.quiet, "quiet", "q", false, "Display only image IDs") + flags.StringVar(&listFlag.sort, "sort", "created", "Sort by "+sortFields.String()) + flags.BoolVarP(&listFlag.history, "history", "", false, "Display the image name history") +} + +func images(cmd *cobra.Command, args []string) error { + if len(listOptions.Filter) > 0 && len(args) > 0 { + return errors.New("cannot specify an image and a filter(s)") + } + + if len(listOptions.Filter) < 1 && len(args) > 0 { + listOptions.Filter = append(listOptions.Filter, "reference="+args[0]) + } + + if cmd.Flag("sort").Changed && !sortFields.Contains(listFlag.sort) { + return fmt.Errorf("\"%s\" is not a valid field for sorting. Choose from: %s", + listFlag.sort, sortFields.String()) + } + + summaries, err := registry.ImageEngine().List(registry.GetContext(), listOptions) + if err != nil { + return err + } + + imageS := summaries + sort.Slice(imageS, sortFunc(listFlag.sort, imageS)) + + if cmd.Flag("format").Changed && listFlag.format == "json" { + return writeJSON(imageS) + } else { + return writeTemplate(imageS, err) + } +} + +func writeJSON(imageS []*entities.ImageSummary) error { + type image struct { + entities.ImageSummary + Created 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.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 { + type image struct { + entities.ImageSummary + Repository string `json:"repository,omitempty"` + Tag string `json:"tag,omitempty"` + } + + imgs := make([]image, 0, len(imageS)) + for _, e := range imageS { + for _, tag := range e.RepoTags { + var h image + h.ImageSummary = *e + h.Repository, h.Tag = tokenRepoTag(tag) + imgs = append(imgs, h) + } + if e.IsReadOnly() { + listFlag.readOnly = true + } + } + + hdr, row := imageListFormat(listFlag) + format := hdr + "{{range . }}" + row + "{{end}}" + + tmpl := template.Must(template.New("report").Funcs(report.PodmanTemplateFuncs()).Parse(format)) + w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) + defer w.Flush() + return tmpl.Execute(w, imgs) +} + +func tokenRepoTag(tag string) (string, string) { + tokens := strings.SplitN(tag, ":", 2) + switch len(tokens) { + case 0: + return tag, "" + case 1: + return tokens[0], "" + case 2: + return tokens[0], tokens[1] + default: + return "<N/A>", "" + } +} + +func sortFunc(key string, data []*entities.ImageSummary) func(i, j int) bool { + switch key { + case "id": + return func(i, j int) bool { + return data[i].ID < data[j].ID + } + case "repository": + return func(i, j int) bool { + return data[i].RepoTags[0] < data[j].RepoTags[0] + } + case "size": + return func(i, j int) bool { + return data[i].Size < data[j].Size + } + case "tag": + return func(i, j int) bool { + return data[i].RepoTags[0] < data[j].RepoTags[0] + } + default: + // case "created": + return func(i, j int) bool { + return data[i].Created >= data[j].Created + } + } +} + +func imageListFormat(flags listFlagType) (string, string) { + if flags.quiet { + return "", "{{slice .ID 0 12}}\n" + } + + // Defaults + hdr := "REPOSITORY\tTAG" + row := "{{.Repository}}\t{{if .Tag}}{{.Tag}}{{else}}<none>{{end}}" + + if flags.digests { + hdr += "\tDIGEST" + row += "\t{{.Digest}}" + } + + hdr += "\tIMAGE ID" + if flags.noTrunc { + row += "\tsha256:{{.ID}}" + } else { + row += "\t{{slice .ID 0 12}}" + } + + hdr += "\tCREATED\tSIZE" + row += "\t{{humanDuration .Created}}\t{{humanSize .Size}}" + + if flags.history { + hdr += "\tHISTORY" + row += "\t{{if .History}}{{join .History \", \"}}{{else}}<none>{{end}}" + } + + if flags.readOnly { + hdr += "\tReadOnly" + row += "\t{{.ReadOnly}}" + } + + if flags.noHeading { + hdr = "" + } else { + hdr += "\n" + } + + row += "\n" + return hdr, row +} diff --git a/cmd/podmanV2/images/prune.go b/cmd/podmanV2/images/prune.go new file mode 100644 index 000000000..6577c458e --- /dev/null +++ b/cmd/podmanV2/images/prune.go @@ -0,0 +1,86 @@ +package images + +import ( + "bufio" + "fmt" + "os" + "strings" + + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/pkg/domain/entities" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + pruneDescription = `Removes all unnamed images from local storage. + + 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, + Short: "Remove unused images", + Long: pruneDescription, + RunE: prune, + Example: `podman image prune`, + } + + pruneOpts = entities.ImagePruneOptions{} + force bool + filter = []string{} +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: pruneCmd, + Parent: imageCmd, + }) + + flags := pruneCmd.Flags() + flags.BoolVarP(&pruneOpts.All, "all", "a", false, "Remove all unused images, not just dangling ones") + flags.BoolVarP(&force, "force", "f", false, "Do not prompt for confirmation") + flags.StringArrayVar(&filter, "filter", []string{}, "Provide filter values (e.g. 'label=<key>=<value>')") + +} + +func prune(cmd *cobra.Command, args []string) error { + if !force { + reader := bufio.NewReader(os.Stdin) + fmt.Printf(` +WARNING! This will remove all dangling images. +Are you sure you want to continue? [y/N] `) + answer, err := reader.ReadString('\n') + if err != nil { + return errors.Wrapf(err, "error reading input") + } + if strings.ToLower(answer)[0] != 'y' { + return nil + } + } + + // TODO Remove once filter refactor is finished and url.Values rules :) + for _, f := range filter { + t := strings.SplitN(f, "=", 2) + pruneOpts.Filters.Add(t[0], t[1]) + } + + results, err := registry.ImageEngine().Prune(registry.GetContext(), pruneOpts) + if err != nil { + return err + } + + for _, i := range results.Report.Id { + fmt.Println(i) + } + + for _, e := range results.Report.Err { + fmt.Fprint(os.Stderr, e.Error()+"\n") + } + + if results.Size > 0 { + fmt.Fprintf(os.Stdout, "Size: %d\n", results.Size) + } + + return nil +} diff --git a/cmd/podmanV2/images/rm.go b/cmd/podmanV2/images/rm.go new file mode 100644 index 000000000..bb5880de3 --- /dev/null +++ b/cmd/podmanV2/images/rm.go @@ -0,0 +1,70 @@ +package images + +import ( + "fmt" + "os" + + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/pkg/domain/entities" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + rmDescription = "Removes one or more previously pulled or locally created images." + rmCmd = &cobra.Command{ + Use: "rm [flags] IMAGE [IMAGE...]", + Short: "Removes one or more images from local storage", + Long: rmDescription, + PreRunE: preRunE, + RunE: rm, + Example: `podman image rm imageID + podman image rm --force alpine + podman image rm c4dfb1609ee2 93fd78260bd1 c0ed59d05ff7`, + } + + imageOpts = entities.ImageDeleteOptions{} +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: rmCmd, + Parent: imageCmd, + }) + + flags := rmCmd.Flags() + 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 { + + 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 + } + } + + for _, u := range report.Untagged { + fmt.Println("Untagged: " + u) + } + for _, d := range report.Deleted { + fmt.Println("Deleted: " + d) + } + return nil +} diff --git a/cmd/podmanV2/images/rmi.go b/cmd/podmanV2/images/rmi.go new file mode 100644 index 000000000..7f9297bc9 --- /dev/null +++ b/cmd/podmanV2/images/rmi.go @@ -0,0 +1,30 @@ +package images + +import ( + "strings" + + "github.com/containers/libpod/cmd/podmanV2/registry" + "github.com/containers/libpod/pkg/domain/entities" + "github.com/spf13/cobra" +) + +var ( + rmiCmd = &cobra.Command{ + Use: strings.Replace(rmCmd.Use, "rm ", "rmi ", 1), + Args: rmCmd.Args, + Short: rmCmd.Short, + Long: rmCmd.Long, + PreRunE: rmCmd.PreRunE, + RunE: rmCmd.RunE, + Example: strings.Replace(rmCmd.Example, "podman image rm", "podman rmi", -1), + } +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, + Command: rmiCmd, + }) + rmiCmd.SetHelpTemplate(registry.HelpTemplate()) + rmiCmd.SetUsageTemplate(registry.UsageTemplate()) +} |