169 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
| package main
 | |
| 
 | |
| import (
 | |
| 	js "encoding/json"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 
 | |
| 	of "github.com/containers/buildah/pkg/formats"
 | |
| 	"github.com/containers/libpod/cmd/podman/cliconfig"
 | |
| 	"github.com/containers/libpod/cmd/podman/libpodruntime"
 | |
| 	"github.com/containers/libpod/pkg/rootless"
 | |
| 	"github.com/pkg/errors"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| 	"github.com/spf13/cobra"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	mountCommand cliconfig.MountValues
 | |
| 
 | |
| 	mountDescription = `podman mount
 | |
|     Lists all mounted containers mount points if no container is specified
 | |
| 
 | |
|   podman mount CONTAINER-NAME-OR-ID
 | |
|     Mounts the specified container and outputs the mountpoint
 | |
| `
 | |
| 
 | |
| 	_mountCommand = &cobra.Command{
 | |
| 		Use:   "mount [flags] [CONTAINER]",
 | |
| 		Short: "Mount a working container's root filesystem",
 | |
| 		Long:  mountDescription,
 | |
| 		RunE: func(cmd *cobra.Command, args []string) error {
 | |
| 			mountCommand.InputArgs = args
 | |
| 			mountCommand.GlobalFlags = MainGlobalOpts
 | |
| 			return mountCmd(&mountCommand)
 | |
| 		},
 | |
| 		Args: func(cmd *cobra.Command, args []string) error {
 | |
| 			return checkAllAndLatest(cmd, args, true)
 | |
| 		},
 | |
| 	}
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	mountCommand.Command = _mountCommand
 | |
| 	mountCommand.SetHelpTemplate(HelpTemplate())
 | |
| 	mountCommand.SetUsageTemplate(UsageTemplate())
 | |
| 	flags := mountCommand.Flags()
 | |
| 	flags.BoolVarP(&mountCommand.All, "all", "a", false, "Mount all containers")
 | |
| 	flags.StringVar(&mountCommand.Format, "format", "", "Change the output format to Go template")
 | |
| 	flags.BoolVarP(&mountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
 | |
| 	flags.BoolVar(&mountCommand.NoTrunc, "notruncate", false, "Do not truncate output")
 | |
| 
 | |
| 	markFlagHiddenForRemoteClient("latest", flags)
 | |
| }
 | |
| 
 | |
| // jsonMountPoint stores info about each container
 | |
| type jsonMountPoint struct {
 | |
| 	ID         string   `json:"id"`
 | |
| 	Names      []string `json:"names"`
 | |
| 	MountPoint string   `json:"mountpoint"`
 | |
| }
 | |
| 
 | |
| func mountCmd(c *cliconfig.MountValues) error {
 | |
| 	runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
 | |
| 	if err != nil {
 | |
| 		return errors.Wrapf(err, "could not get runtime")
 | |
| 	}
 | |
| 	defer runtime.Shutdown(false)
 | |
| 
 | |
| 	if os.Geteuid() != 0 {
 | |
| 		rtc, err := runtime.GetConfig()
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		if driver := rtc.StorageConfig.GraphDriverName; driver != "vfs" {
 | |
| 			// Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part
 | |
| 			// of the mount command.
 | |
| 			return fmt.Errorf("cannot mount using driver %s in rootless mode", driver)
 | |
| 		}
 | |
| 
 | |
| 		became, ret, err := rootless.BecomeRootInUserNS()
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		if became {
 | |
| 			os.Exit(ret)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if c.All && c.Latest {
 | |
| 		return errors.Errorf("--all and --latest cannot be used together")
 | |
| 	}
 | |
| 
 | |
| 	mountContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
 | |
| 	if err != nil {
 | |
| 		if len(mountContainers) == 0 {
 | |
| 			return err
 | |
| 		}
 | |
| 		fmt.Println(err.Error())
 | |
| 	}
 | |
| 
 | |
| 	formats := map[string]bool{
 | |
| 		"":            true,
 | |
| 		of.JSONString: true,
 | |
| 	}
 | |
| 
 | |
| 	json := c.Format == of.JSONString
 | |
| 	if !formats[c.Format] {
 | |
| 		return errors.Errorf("%q is not a supported format", c.Format)
 | |
| 	}
 | |
| 
 | |
| 	var lastError error
 | |
| 	if len(mountContainers) > 0 {
 | |
| 		for _, ctr := range mountContainers {
 | |
| 			if json {
 | |
| 				if lastError != nil {
 | |
| 					logrus.Error(lastError)
 | |
| 				}
 | |
| 				lastError = errors.Wrapf(err, "json option cannot be used with a container id")
 | |
| 				continue
 | |
| 			}
 | |
| 			mountPoint, err := ctr.Mount()
 | |
| 			if err != nil {
 | |
| 				if lastError != nil {
 | |
| 					logrus.Error(lastError)
 | |
| 				}
 | |
| 				lastError = errors.Wrapf(err, "error mounting container %q", ctr.ID())
 | |
| 				continue
 | |
| 			}
 | |
| 			fmt.Printf("%s\n", mountPoint)
 | |
| 		}
 | |
| 		return lastError
 | |
| 	} else {
 | |
| 		jsonMountPoints := []jsonMountPoint{}
 | |
| 		containers, err2 := runtime.GetContainers()
 | |
| 		if err2 != nil {
 | |
| 			return errors.Wrapf(err2, "error reading list of all containers")
 | |
| 		}
 | |
| 		for _, container := range containers {
 | |
| 			mounted, mountPoint, err := container.Mounted()
 | |
| 			if err != nil {
 | |
| 				return errors.Wrapf(err, "error getting mountpoint for %q", container.ID())
 | |
| 			}
 | |
| 
 | |
| 			if !mounted {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			if json {
 | |
| 				jsonMountPoints = append(jsonMountPoints, jsonMountPoint{ID: container.ID(), Names: []string{container.Name()}, MountPoint: mountPoint})
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			if c.NoTrunc {
 | |
| 				fmt.Printf("%-64s %s\n", container.ID(), mountPoint)
 | |
| 			} else {
 | |
| 				fmt.Printf("%-12.12s %s\n", container.ID(), mountPoint)
 | |
| 			}
 | |
| 		}
 | |
| 		if json {
 | |
| 			data, err := js.MarshalIndent(jsonMountPoints, "", "    ")
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			fmt.Printf("%s\n", data)
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 |