aboutsummaryrefslogtreecommitdiff
path: root/cmd/podman/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/main.go')
-rw-r--r--cmd/podman/main.go303
1 files changed, 135 insertions, 168 deletions
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 8c08b2bfb..32ecaede7 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -6,9 +6,10 @@ import (
"os"
"os/exec"
"runtime/pprof"
- "sort"
+ "strings"
"syscall"
+ "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
_ "github.com/containers/libpod/pkg/hooks/0.1.0"
"github.com/containers/libpod/pkg/rootless"
@@ -17,7 +18,7 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
lsyslog "github.com/sirupsen/logrus/hooks/syslog"
- "github.com/urfave/cli"
+ "github.com/spf13/cobra"
)
// This is populated by the Makefile from the VERSION file
@@ -26,198 +27,159 @@ var (
exitCode = 125
)
-var cmdsNotRequiringRootless = map[string]bool{
- "help": true,
- "version": true,
- "create": true,
- "exec": true,
- "export": true,
- // `info` must be executed in an user namespace.
- // If this change, please also update libpod.refreshRootless()
- "login": true,
- "logout": true,
- "mount": true,
- "kill": true,
- "pause": true,
- "restart": true,
- "run": true,
- "unpause": true,
- "search": true,
- "stats": true,
- "stop": true,
- "top": true,
+var cmdsNotRequiringRootless = map[*cobra.Command]bool{
+ _versionCommand: true,
+ _createCommand: true,
+ _execCommand: true,
+ _exportCommand: true,
+ //// `info` must be executed in an user namespace.
+ //// If this change, please also update libpod.refreshRootless()
+ _loginCommand: true,
+ _logoutCommand: true,
+ _mountCommand: true,
+ _killCommand: true,
+ _pauseCommand: true,
+ _restartCommand: true,
+ _runCommmand: true,
+ _unpauseCommand: true,
+ _searchCommand: true,
+ _statsCommand: true,
+ _stopCommand: true,
+ _topCommand: true,
}
-type commandSorted []cli.Command
-
-func (a commandSorted) Len() int { return len(a) }
-func (a commandSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-
-type commandSortedAlpha struct{ commandSorted }
-
-func (a commandSortedAlpha) Less(i, j int) bool {
- return a.commandSorted[i].Name < a.commandSorted[j].Name
+var rootCmd = &cobra.Command{
+ Use: "podman",
+ Long: "manage pods and images",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ return cmd.Help()
+ },
+ PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+ return before(cmd, args)
+ },
+ PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
+ return after(cmd, args)
+ },
+ SilenceUsage: true,
+ SilenceErrors: true,
}
-type flagSorted []cli.Flag
-
-func (a flagSorted) Len() int { return len(a) }
-func (a flagSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+var MainGlobalOpts cliconfig.MainFlags
+
+func init() {
+ cobra.OnInitialize(initConfig)
+ rootCmd.TraverseChildren = true
+ rootCmd.Version = version.Version
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CGroupManager, "cgroup-manager", "", "Cgroup manager to use (cgroupfs or systemd, default systemd)")
+ // -c is deprecated due to conflict with -c on subcommands
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CpuProfile, "cpu-profile", "", "Path for the cpu profiling results")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Config, "config", "", "Path of a libpod config file detailing container server configuration options")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.ConmonPath, "conmon", "", "Path of the conmon binary")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CniConfigDir, "cni-config-dir", "", "Path of the configuration directory for CNI networks")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.DefaultMountsFile, "default-mounts-file", "", "Path to default mounts file")
+ rootCmd.PersistentFlags().MarkHidden("defaults-mount-file")
+ rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.HooksDir, "hooks-dir", []string{}, "Set the OCI hooks directory path (may be set multiple times)")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", "Log messages above specified level: debug, info, warn, error (default), fatal or panic")
+ rootCmd.PersistentFlags().IntVar(&MainGlobalOpts.MaxWorks, "max-workers", 0, "The maximum number of workers for parallel operations")
+ rootCmd.PersistentFlags().MarkHidden("max-workers")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Namespace, "namespace", "", "Set the libpod namespace, used to create separate views of the containers and pods on the system")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Root, "root", "", "Path to the root directory in which data, including images, is stored")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runtime, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc")
+ // -s is depracated due to conflict with -s on subcommands
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.StorageDriver, "storage-driver", "", "Select which storage driver is used to manage storage of images and containers (default is overlay)")
+ rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver")
+ rootCmd.PersistentFlags().BoolVar(&MainGlobalOpts.Syslog, "syslog", false, "Output logging information to syslog as well as the console")
+
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.TmpDir, "tmpdir", "", "Path to the tmp directory")
-type flagSortedAlpha struct{ flagSorted }
-
-func (a flagSortedAlpha) Less(i, j int) bool {
- return a.flagSorted[i].GetName() < a.flagSorted[j].GetName()
+}
+func initConfig() {
+ // we can do more stuff in here.
}
-func main() {
- debug := false
- cpuProfile := false
-
- if reexec.Init() {
- return
- }
-
- app := cli.NewApp()
- app.Name = "podman"
- app.Usage = "manage pods and images"
- app.OnUsageError = usageErrorHandler
- app.CommandNotFound = commandNotFoundHandler
-
- app.Version = version.Version
-
- app.Commands = []cli.Command{
- containerCommand,
- exportCommand,
- historyCommand,
- imageCommand,
- imagesCommand,
- importCommand,
- infoCommand,
- inspectCommand,
- pullCommand,
- rmiCommand,
- systemCommand,
- tagCommand,
- versionCommand,
- }
-
- app.Commands = append(app.Commands, getAppCommands()...)
- sort.Sort(commandSortedAlpha{app.Commands})
-
- if varlinkCommand != nil {
- app.Commands = append(app.Commands, *varlinkCommand)
+func before(cmd *cobra.Command, args []string) error {
+ if err := libpod.SetXdgRuntimeDir(""); err != nil {
+ logrus.Errorf(err.Error())
+ os.Exit(1)
}
-
- app.Before = func(c *cli.Context) error {
- if err := libpod.SetXdgRuntimeDir(""); err != nil {
- logrus.Errorf(err.Error())
- os.Exit(1)
- }
- args := c.Args()
- if args.Present() && rootless.IsRootless() {
- if _, notRequireRootless := cmdsNotRequiringRootless[args.First()]; !notRequireRootless {
- became, ret, err := rootless.BecomeRootInUserNS()
- if err != nil {
- logrus.Errorf(err.Error())
- os.Exit(1)
- }
- if became {
- os.Exit(ret)
- }
+ if rootless.IsRootless() {
+ notRequireRootless := cmdsNotRequiringRootless[cmd]
+ if !notRequireRootless && !strings.HasPrefix(cmd.Use, "help") {
+ became, ret, err := rootless.BecomeRootInUserNS()
+ if err != nil {
+ logrus.Errorf(err.Error())
+ os.Exit(1)
}
- }
- if c.GlobalBool("syslog") {
- hook, err := lsyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
- if err == nil {
- logrus.AddHook(hook)
+ if became {
+ os.Exit(ret)
}
}
- logLevel := c.GlobalString("log-level")
- if logLevel != "" {
- level, err := logrus.ParseLevel(logLevel)
- if err != nil {
- return err
- }
+ }
- logrus.SetLevel(level)
+ if MainGlobalOpts.Syslog {
+ hook, err := lsyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
+ if err == nil {
+ logrus.AddHook(hook)
}
+ }
- rlimits := new(syscall.Rlimit)
- rlimits.Cur = 1048576
- rlimits.Max = 1048576
- if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
- if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
- return errors.Wrapf(err, "error getting rlimits")
- }
- rlimits.Cur = rlimits.Max
- if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
- return errors.Wrapf(err, "error setting new rlimits")
- }
+ // Set log level
+ level, err := logrus.ParseLevel(MainGlobalOpts.LogLevel)
+ if err != nil {
+ return err
+ }
+ logrus.SetLevel(level)
+
+ rlimits := new(syscall.Rlimit)
+ rlimits.Cur = 1048576
+ rlimits.Max = 1048576
+ if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
+ if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
+ return errors.Wrapf(err, "error getting rlimits")
}
-
- if rootless.IsRootless() {
- logrus.Info("running as rootless")
+ rlimits.Cur = rlimits.Max
+ if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
+ return errors.Wrapf(err, "error setting new rlimits")
}
+ }
- // Be sure we can create directories with 0755 mode.
- syscall.Umask(0022)
+ if rootless.IsRootless() {
+ logrus.Info("running as rootless")
+ }
- if logLevel == "debug" {
- debug = true
+ // Be sure we can create directories with 0755 mode.
+ syscall.Umask(0022)
+ if cmd.Flag("cpu-profile").Changed {
+ f, err := os.Create(MainGlobalOpts.CpuProfile)
+ if err != nil {
+ return errors.Wrapf(err, "unable to create cpu profiling file %s",
+ MainGlobalOpts.CpuProfile)
}
- if c.GlobalIsSet("cpu-profile") {
- f, err := os.Create(c.GlobalString("cpu-profile"))
- if err != nil {
- return errors.Wrapf(err, "unable to create cpu profiling file %s",
- c.GlobalString("cpu-profile"))
- }
- cpuProfile = true
- pprof.StartCPUProfile(f)
- }
- return nil
- }
- app.After = func(*cli.Context) error {
- // called by Run() when the command handler succeeds
- if cpuProfile {
- pprof.StopCPUProfile()
- }
- return nil
- }
- app.Flags = []cli.Flag{
- cli.StringFlag{
- Name: "config, c",
- Usage: "Path of a libpod config file detailing container server configuration options",
- Hidden: true,
- },
- cli.StringFlag{
- Name: "cpu-profile",
- Usage: "Path for the cpu profiling results",
- },
- cli.StringFlag{
- Name: "log-level",
- Usage: "Log messages above specified level: debug, info, warn, error (default), fatal or panic",
- Value: "error",
- },
- cli.StringFlag{
- Name: "tmpdir",
- Usage: "Path to the tmp directory",
- },
+ pprof.StartCPUProfile(f)
}
+ return nil
+}
- app.Flags = append(app.Flags, getMainAppFlags()...)
- sort.Sort(flagSortedAlpha{app.Flags})
+func after(cmd *cobra.Command, args []string) error {
+ if cmd.Flag("cpu-profile").Changed {
+ pprof.StopCPUProfile()
+ }
+ return nil
+}
- // Check if /etc/containers/registries.conf exists when running in
- // in a local environment.
- CheckForRegistries()
+func main() {
+ //debug := false
+ //cpuProfile := false
- if err := app.Run(os.Args); err != nil {
- if debug {
+ if reexec.Init() {
+ return
+ }
+ if err := rootCmd.Execute(); err != nil {
+ if MainGlobalOpts.LogLevel == "debug" {
logrus.Errorf(err.Error())
} else {
- // Retrieve the exit error from the exec call, if it exists
if ee, ok := err.(*exec.ExitError); ok {
if status, ok := ee.Sys().(syscall.WaitStatus); ok {
exitCode = status.ExitStatus()
@@ -233,6 +195,11 @@ func main() {
if exitCode == 125 {
exitCode = 0
}
+
}
+
+ // Check if /etc/containers/registries.conf exists when running in
+ // in a local environment.
+ CheckForRegistries()
os.Exit(exitCode)
}