// Boot starts Clair. By exporting this function, anyone can import their own // custom fetchers/updaters into their own package and then call clair.Boot. func Boot(config *config.Config) { rand.Seed(time.Now().UnixNano()) st := utils.NewStopper() // Open database db, err := pgsql.Open(config.Database) if err != nil { log.Fatal(err) } defer db.Close() // Start notifier st.Begin() go notifier.Run(config.Notifier, db, st) // Start API st.Begin() go api.Run(config.API, &context.RouteContext{db, config.API}, st) st.Begin() go api.RunHealth(config.API, &context.RouteContext{db, config.API}, st) // Start updater st.Begin() go updater.Run(config.Updater, db, st) // Wait for interruption and shutdown gracefully. waitForSignals(os.Interrupt) log.Info("Received interruption, gracefully stopping ...") st.Stop() }
func main() { rand.Seed(time.Now().UTC().UnixNano()) var err error st := utils.NewStopper() // Parse command-line arguments kingpin.Parse() if *cfgDbType != "memstore" && *cfgDbPath == "" { kingpin.Errorf("required flag --db-path not provided, try --help") os.Exit(1) } if *cfgNotifierType == "http" && *cfgNotifierHTTPURL == "" { kingpin.Errorf("required flag --notifier-http-url not provided, try --help") os.Exit(1) } // Initialize error/logging system logLevel, err := capnslog.ParseLevel(strings.ToUpper(*cfgLogLevel)) capnslog.SetGlobalLogLevel(logLevel) capnslog.SetFormatter(capnslog.NewPrettyFormatter(os.Stdout, false)) // Enable CPU Profiling if specified if *cfgCPUProfilePath != "" { f, err := os.Create(*cfgCPUProfilePath) if err != nil { log.Fatalf("failed to create profile file: %s", err) } defer f.Close() pprof.StartCPUProfile(f) log.Info("started profiling") defer func() { pprof.StopCPUProfile() log.Info("stopped profiling") }() } // Open database err = database.Open(*cfgDbType, *cfgDbPath) if err != nil { log.Fatal(err) } defer database.Close() // Start notifier var notifierService notifier.Notifier switch *cfgNotifierType { case "http": notifierService, err = notifier.NewHTTPNotifier(*cfgNotifierHTTPURL) if err != nil { log.Fatalf("could not initialize HTTP notifier: %s", err) } } if notifierService != nil { st.Begin() go notifierService.Run(st) } // Start Main API and Health API st.Begin() go api.RunMain(&api.Config{ Port: *cfgAPIPort, TimeOut: *cfgAPITimeout, CertFile: *cfgAPICertFile, KeyFile: *cfgAPIKeyFile, CAFile: *cfgAPICAFile, }, st) st.Begin() go api.RunHealth(*cfgAPIPort+1, st) // Start updater st.Begin() go updater.Run(*cfgUpdateInterval, st) // This blocks the main goroutine which is required to keep all the other goroutines running interrupts := make(chan os.Signal, 1) signal.Notify(interrupts, os.Interrupt) <-interrupts log.Info("Received interruption, gracefully stopping ...") st.Stop() }