diff options
author | baude <bbaude@redhat.com> | 2019-01-31 13:20:04 -0600 |
---|---|---|
committer | baude <bbaude@redhat.com> | 2019-02-08 10:26:43 -0600 |
commit | 25a3923b61a5ca014318e6d957f68abd03947297 (patch) | |
tree | 2ccb4a0bd9bda70c1c258dcb1b8aca8961d9ad30 /cmd/podman/main.go | |
parent | 962850c6e0dfcee926af31fc0ad24f1f6c26f8ac (diff) | |
download | podman-25a3923b61a5ca014318e6d957f68abd03947297.tar.gz podman-25a3923b61a5ca014318e6d957f68abd03947297.tar.bz2 podman-25a3923b61a5ca014318e6d957f68abd03947297.zip |
Migrate to cobra CLI
We intend to migrate to the cobra cli from urfave/cli because the
project is more well maintained. There are also some technical reasons
as well which extend into our remote client work.
Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'cmd/podman/main.go')
-rw-r--r-- | cmd/podman/main.go | 303 |
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) } |