summaryrefslogtreecommitdiff
path: root/cmd/podman/images/mount.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/images/mount.go')
-rw-r--r--cmd/podman/images/mount.go139
1 files changed, 139 insertions, 0 deletions
diff --git a/cmd/podman/images/mount.go b/cmd/podman/images/mount.go
new file mode 100644
index 000000000..fac06e324
--- /dev/null
+++ b/cmd/podman/images/mount.go
@@ -0,0 +1,139 @@
+package images
+
+import (
+ "fmt"
+ "os"
+ "text/tabwriter"
+ "text/template"
+
+ "github.com/containers/podman/v2/cmd/podman/registry"
+ "github.com/containers/podman/v2/cmd/podman/utils"
+ "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+var (
+ mountDescription = `podman image mount
+ Lists all mounted images mount points if no images is specified
+
+ podman image mount IMAGE-NAME-OR-ID
+ Mounts the specified image and prints the mountpoint
+`
+
+ mountCommand = &cobra.Command{
+ Use: "mount [flags] [IMAGE...]",
+ Short: "Mount an images's root filesystem",
+ Long: mountDescription,
+ RunE: mount,
+ Example: `podman image mount imgID
+ podman image mount imgID1 imgID2 imgID3
+ podman image mount
+ podman image mount --all`,
+ Annotations: map[string]string{
+ registry.UnshareNSRequired: "",
+ registry.ParentNSRequired: "",
+ },
+ }
+)
+
+var (
+ mountOpts entities.ImageMountOptions
+)
+
+func mountFlags(flags *pflag.FlagSet) {
+ flags.BoolVarP(&mountOpts.All, "all", "a", false, "Mount all images")
+ flags.StringVar(&mountOpts.Format, "format", "", "Print the mounted images in specified format (json)")
+}
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: mountCommand,
+ Parent: imageCmd,
+ })
+ mountFlags(mountCommand.Flags())
+}
+
+func mount(_ *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ if len(args) > 0 && mountOpts.All {
+ return errors.New("when using the --all switch, you may not pass any image names or IDs")
+ }
+ reports, err := registry.ImageEngine().Mount(registry.GetContext(), args, mountOpts)
+ if err != nil {
+ return err
+ }
+ if len(args) > 0 || mountOpts.All {
+ for _, r := range reports {
+ if r.Err == nil {
+ fmt.Println(r.Path)
+ continue
+ }
+ errs = append(errs, r.Err)
+ }
+ return errs.PrintErrors()
+ }
+
+ switch mountOpts.Format {
+ case "json":
+ return printJSON(reports)
+ case "":
+ // do nothing
+ default:
+ return errors.Errorf("unknown --format argument: %s", mountOpts.Format)
+ }
+
+ mrs := make([]mountReporter, 0, len(reports))
+ for _, r := range reports {
+ mrs = append(mrs, mountReporter{r})
+ }
+ row := "{{.ID}} {{.Path}}\n"
+ format := "{{range . }}" + row + "{{end}}"
+ tmpl, err := template.New("mounts").Parse(format)
+ if err != nil {
+ return err
+ }
+ w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+ defer w.Flush()
+ return tmpl.Execute(w, mrs)
+}
+
+func printJSON(reports []*entities.ImageMountReport) error {
+ type jreport struct {
+ ID string `json:"id"`
+ Names []string
+ Repositories []string
+ Mountpoint string `json:"mountpoint"`
+ }
+ jreports := make([]jreport, 0, len(reports))
+
+ for _, r := range reports {
+ jreports = append(jreports, jreport{
+ ID: r.Id,
+ Names: []string{r.Name},
+ Repositories: r.Repositories,
+ Mountpoint: r.Path,
+ })
+ }
+ b, err := json.MarshalIndent(jreports, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(b))
+ return nil
+}
+
+type mountReporter struct {
+ *entities.ImageMountReport
+}
+
+func (m mountReporter) ID() string {
+ if len(m.Repositories) > 0 {
+ return m.Repositories[0]
+ }
+ return m.Id
+}