github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/cmd/podmanV2/root.go (about) 1 package main 2 3 import ( 4 "context" 5 "fmt" 6 "log/syslog" 7 "os" 8 "path" 9 "runtime/pprof" 10 11 "github.com/containers/libpod/cmd/podmanV2/registry" 12 "github.com/containers/libpod/pkg/domain/entities" 13 "github.com/containers/libpod/pkg/rootless" 14 "github.com/containers/libpod/pkg/tracing" 15 "github.com/containers/libpod/version" 16 "github.com/opentracing/opentracing-go" 17 "github.com/pkg/errors" 18 "github.com/sirupsen/logrus" 19 logrusSyslog "github.com/sirupsen/logrus/hooks/syslog" 20 "github.com/spf13/cobra" 21 "github.com/spf13/pflag" 22 ) 23 24 var ( 25 rootCmd = &cobra.Command{ 26 Use: path.Base(os.Args[0]), 27 Long: "Manage pods, containers and images", 28 SilenceUsage: true, 29 SilenceErrors: true, 30 TraverseChildren: true, 31 PersistentPreRunE: preRunE, 32 RunE: registry.SubCommandExists, 33 PersistentPostRunE: postRunE, 34 Version: version.Version, 35 } 36 37 logLevels = entities.NewStringSet("debug", "info", "warn", "error", "fatal", "panic") 38 logLevel = "error" 39 useSyslog bool 40 ) 41 42 func init() { 43 cobra.OnInitialize( 44 rootlessHook, 45 loggingHook, 46 syslogHook, 47 ) 48 49 rootFlags(registry.PodmanOptions, rootCmd.PersistentFlags()) 50 } 51 52 func Execute() { 53 if err := rootCmd.ExecuteContext(registry.GetContextWithOptions()); err != nil { 54 logrus.Error(err) 55 } else if registry.GetExitCode() == registry.ExecErrorCodeGeneric { 56 // The exitCode modified from registry.ExecErrorCodeGeneric, 57 // indicates an application 58 // running inside of a container failed, as opposed to the 59 // podman command failed. Must exit with that exit code 60 // otherwise command exited correctly. 61 registry.SetExitCode(0) 62 } 63 os.Exit(registry.GetExitCode()) 64 } 65 66 func preRunE(cmd *cobra.Command, _ []string) error { 67 // Update PodmanOptions now that we "know" more 68 // TODO: pass in path overriding configuration file 69 registry.PodmanOptions = registry.NewPodmanConfig() 70 71 cmd.SetHelpTemplate(registry.HelpTemplate()) 72 cmd.SetUsageTemplate(registry.UsageTemplate()) 73 74 if cmd.Flag("cpu-profile").Changed { 75 f, err := os.Create(registry.PodmanOptions.CpuProfile) 76 if err != nil { 77 return errors.Wrapf(err, "unable to create cpu profiling file %s", 78 registry.PodmanOptions.CpuProfile) 79 } 80 if err := pprof.StartCPUProfile(f); err != nil { 81 return err 82 } 83 } 84 85 if cmd.Flag("trace").Changed { 86 tracer, closer := tracing.Init("podman") 87 opentracing.SetGlobalTracer(tracer) 88 registry.PodmanOptions.SpanCloser = closer 89 90 registry.PodmanOptions.Span = tracer.StartSpan("before-context") 91 registry.PodmanOptions.SpanCtx = opentracing.ContextWithSpan(context.Background(), registry.PodmanOptions.Span) 92 } 93 return nil 94 } 95 96 func postRunE(cmd *cobra.Command, args []string) error { 97 if cmd.Flag("cpu-profile").Changed { 98 pprof.StopCPUProfile() 99 } 100 if cmd.Flag("trace").Changed { 101 registry.PodmanOptions.Span.Finish() 102 registry.PodmanOptions.SpanCloser.Close() 103 } 104 return nil 105 } 106 107 func loggingHook() { 108 if !logLevels.Contains(logLevel) { 109 logrus.Errorf("Log Level \"%s\" is not supported, choose from: %s", logLevel, logLevels.String()) 110 os.Exit(1) 111 } 112 113 level, err := logrus.ParseLevel(logLevel) 114 if err != nil { 115 fmt.Fprintf(os.Stderr, err.Error()) 116 os.Exit(1) 117 } 118 logrus.SetLevel(level) 119 120 if logrus.IsLevelEnabled(logrus.InfoLevel) { 121 logrus.Infof("%s filtering at log level %s", os.Args[0], logrus.GetLevel()) 122 } 123 } 124 125 func syslogHook() { 126 if useSyslog { 127 hook, err := logrusSyslog.NewSyslogHook("", "", syslog.LOG_INFO, "") 128 if err != nil { 129 logrus.WithError(err).Error("Failed to initialize syslog hook") 130 } 131 if err == nil { 132 logrus.AddHook(hook) 133 } 134 } 135 } 136 137 func rootlessHook() { 138 if rootless.IsRootless() { 139 logrus.Error("rootless mode is currently not supported. Support will return ASAP.") 140 } 141 // ce, err := registry.NewContainerEngine(rootCmd, []string{}) 142 // if err != nil { 143 // logrus.WithError(err).Fatal("failed to obtain container engine") 144 // } 145 // ce.SetupRootLess(rootCmd) 146 } 147 148 func rootFlags(opts entities.PodmanConfig, flags *pflag.FlagSet) { 149 // V2 flags 150 flags.StringVarP(&opts.Uri, "remote", "r", "", "URL to access Podman service") 151 flags.StringSliceVar(&opts.Identities, "identity", []string{}, "path to SSH identity file") 152 153 // Override default --help information of `--version` global flag 154 // TODO: restore -v option for version without breaking -v for volumes 155 var dummyVersion bool 156 flags.BoolVar(&dummyVersion, "version", false, "Version of Podman") 157 158 cfg := opts.Config 159 flags.StringVar(&cfg.Engine.CgroupManager, "cgroup-manager", cfg.Engine.CgroupManager, opts.CGroupUsage) 160 flags.StringVar(&opts.CpuProfile, "cpu-profile", "", "Path for the cpu profiling results") 161 flags.StringVar(&opts.ConmonPath, "conmon", "", "Path of the conmon binary") 162 flags.StringVar(&cfg.Engine.NetworkCmdPath, "network-cmd-path", cfg.Engine.NetworkCmdPath, "Path to the command for configuring the network") 163 flags.StringVar(&cfg.Network.NetworkConfigDir, "cni-config-dir", cfg.Network.NetworkConfigDir, "Path of the configuration directory for CNI networks") 164 flags.StringVar(&cfg.Containers.DefaultMountsFile, "default-mounts-file", cfg.Containers.DefaultMountsFile, "Path to default mounts file") 165 flags.StringVar(&cfg.Engine.EventsLogger, "events-backend", cfg.Engine.EventsLogger, `Events backend to use ("file"|"journald"|"none")`) 166 flags.StringSliceVar(&cfg.Engine.HooksDir, "hooks-dir", cfg.Engine.HooksDir, "Set the OCI hooks directory path (may be set multiple times)") 167 flags.IntVar(&opts.MaxWorks, "max-workers", 0, "The maximum number of workers for parallel operations") 168 flags.StringVar(&cfg.Engine.Namespace, "namespace", cfg.Engine.Namespace, "Set the libpod namespace, used to create separate views of the containers and pods on the system") 169 flags.StringVar(&cfg.Engine.StaticDir, "root", "", "Path to the root directory in which data, including images, is stored") 170 flags.StringVar(&opts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored") 171 flags.StringVar(&opts.RuntimePath, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc") 172 // -s is deprecated due to conflict with -s on subcommands 173 flags.StringVar(&opts.StorageDriver, "storage-driver", "", "Select which storage driver is used to manage storage of images and containers (default is overlay)") 174 flags.StringArrayVar(&opts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver") 175 176 flags.StringVar(&opts.Engine.TmpDir, "tmpdir", "", "Path to the tmp directory for libpod state content.\n\nNote: use the environment variable 'TMPDIR' to change the temporary storage location for container images, '/var/tmp'.\n") 177 flags.BoolVar(&opts.Trace, "trace", false, "Enable opentracing output (default false)") 178 179 // Override default --help information of `--help` global flag 180 var dummyHelp bool 181 flags.BoolVar(&dummyHelp, "help", false, "Help for podman") 182 flags.StringVar(&logLevel, "log-level", logLevel, fmt.Sprintf("Log messages above specified level (%s)", logLevels.String())) 183 184 // Hide these flags for both ABI and Tunneling 185 for _, f := range []string{ 186 "cpu-profile", 187 "default-mounts-file", 188 "max-workers", 189 "trace", 190 } { 191 if err := flags.MarkHidden(f); err != nil { 192 logrus.Warnf("unable to mark %s flag as hidden", f) 193 } 194 } 195 196 // Only create these flags for ABI connections 197 if !registry.IsRemote() { 198 flags.BoolVar(&useSyslog, "syslog", false, "Output logging information to syslog as well as the console (default false)") 199 } 200 201 }