package cmd import ( "fmt" "os" "github.com/gookit/color" "github.com/spf13/cobra" "github.com/anchore/syft/syft/presenter" "github.com/anchore/syft/syft/source" "github.com/anchore/stereoscope" "github.com/anchore/syft/internal/config" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/logger" "github.com/anchore/syft/syft" "github.com/spf13/viper" "github.com/wagoodman/go-partybus" "gopkg.in/yaml.v2" ) var appConfig *config.Application var eventBus *partybus.Bus var eventSubscription *partybus.Subscription var cliOpts = config.CliOnlyOptions{} func init() { setGlobalCliOptions() cobra.OnInitialize( initAppConfig, initLogging, logAppConfig, initEventBus, ) } func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } } func setGlobalCliOptions() { rootCmd.PersistentFlags().StringVarP(&cliOpts.ConfigPath, "config", "c", "", "application config file") // scan options flag := "scope" rootCmd.Flags().StringP( "scope", "s", source.SquashedScope.String(), fmt.Sprintf("selection of layers to catalog, options=%v", source.AllScopes)) if err := viper.BindPFlag(flag, rootCmd.Flags().Lookup(flag)); err != nil { fmt.Printf("unable to bind flag '%s': %+v", flag, err) os.Exit(1) } // output & formatting options flag = "output" rootCmd.Flags().StringP( flag, "o", string(presenter.TablePresenter), fmt.Sprintf("report output formatter, options=%v", presenter.Options), ) if err := viper.BindPFlag(flag, rootCmd.Flags().Lookup(flag)); err != nil { fmt.Printf("unable to bind flag '%s': %+v", flag, err) os.Exit(1) } flag = "quiet" rootCmd.Flags().BoolP( flag, "q", false, "suppress all logging output", ) if err := viper.BindPFlag(flag, rootCmd.Flags().Lookup(flag)); err != nil { fmt.Printf("unable to bind flag '%s': %+v", flag, err) os.Exit(1) } rootCmd.Flags().CountVarP(&cliOpts.Verbosity, "verbose", "v", "increase verbosity (-v = info, -vv = debug)") } func initAppConfig() { cfg, err := config.LoadConfigFromFile(viper.GetViper(), &cliOpts) if err != nil { fmt.Printf("failed to load application config: \n\t%+v\n", err) os.Exit(1) } appConfig = cfg } func initLogging() { cfg := logger.LogrusConfig{ EnableConsole: (appConfig.Log.FileLocation == "" || appConfig.CliOptions.Verbosity > 0) && !appConfig.Quiet, EnableFile: appConfig.Log.FileLocation != "", Level: appConfig.Log.LevelOpt, Structured: appConfig.Log.Structured, FileLocation: appConfig.Log.FileLocation, } logWrapper := logger.NewLogrusLogger(cfg) syft.SetLogger(logWrapper) stereoscope.SetLogger(&logger.LogrusNestedLogger{ Logger: logWrapper.Logger.WithField("from-lib", "stereoscope"), }) } func logAppConfig() { appCfgStr, err := yaml.Marshal(&appConfig) if err != nil { log.Debugf("Could not display application config: %+v", err) } else { log.Debugf("Application config:\n%+v", color.Magenta.Sprint(string(appCfgStr))) } } func initEventBus() { eventBus = partybus.NewBus() eventSubscription = eventBus.Subscribe() stereoscope.SetBus(eventBus) syft.SetBus(eventBus) }