func handleSignals() { c := make(chan os.Signal, 1) // SIGTERM is not exactly portable, but Go has a fake signal for it // with Windows so it being there should theoretically not break it // running on windows signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP) // if we receive a SIGINT or SIGTERM, do cleanup here. go func() { for sig := range c { if sig == os.Interrupt || sig == syscall.SIGTERM { logger.Infof("cleaning up...") if config.Config.FreezeData { if config.Config.DataStoreFile != "" { ds := datastore.New() if err := ds.Save(config.Config.DataStoreFile); err != nil { logger.Errorf(err.Error()) } } if err := indexer.SaveIndex(); err != nil { logger.Errorf(err.Error()) } } if config.UsingDB() { datastore.Dbh.Close() } if config.Config.UseSerf { serfin.Serfer.Close() } os.Exit(0) } else if sig == syscall.SIGHUP { logger.Infof("Reloading configuration...") config.ParseConfigOptions() } } }() }
func main() { config.ParseConfigOptions() /* Here goes nothing, db... */ if config.UsingDB() { var derr error if config.Config.UseMySQL { datastore.Dbh, derr = datastore.ConnectDB("mysql", config.Config.MySQL) } else if config.Config.UsePostgreSQL { datastore.Dbh, derr = datastore.ConnectDB("postgres", config.Config.PostgreSQL) } if derr != nil { logger.Criticalf(derr.Error()) os.Exit(1) } } gobRegister() ds := datastore.New() indexer.Initialize(config.Config) if config.Config.FreezeData { if config.Config.DataStoreFile != "" { uerr := ds.Load(config.Config.DataStoreFile) if uerr != nil { logger.Criticalf(uerr.Error()) os.Exit(1) } } ierr := indexer.LoadIndex() if ierr != nil { logger.Criticalf(ierr.Error()) os.Exit(1) } } setSaveTicker() setLogEventPurgeTicker() /* handle import/export */ if config.Config.DoExport { fmt.Printf("Exporting data to %s....\n", config.Config.ImpExFile) err := exportAll(config.Config.ImpExFile) if err != nil { logger.Criticalf("Something went wrong during the export: %s", err.Error()) os.Exit(1) } fmt.Println("All done!") os.Exit(0) } else if config.Config.DoImport { fmt.Printf("Importing data from %s....\n", config.Config.ImpExFile) err := importAll(config.Config.ImpExFile) if err != nil { logger.Criticalf("Something went wrong during the import: %s", err.Error()) os.Exit(1) } if config.Config.FreezeData { if config.Config.DataStoreFile != "" { ds := datastore.New() if err := ds.Save(config.Config.DataStoreFile); err != nil { logger.Errorf(err.Error()) } } if err := indexer.SaveIndex(); err != nil { logger.Errorf(err.Error()) } } if config.UsingDB() { datastore.Dbh.Close() } fmt.Println("All done.") os.Exit(0) } /* Set up serf */ if config.Config.UseSerf { serferr := serfin.StartSerfin() if serferr != nil { logger.Criticalf(serferr.Error()) os.Exit(1) } errch := make(chan error) go startEventMonitor(serfin.Serfer, errch) err := <-errch if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } startNodeMonitor() } /* Create default clients and users. Currently chef-validator, * chef-webui, and admin. */ createDefaultActors() handleSignals() /* Register the various handlers, found in their own source files. */ http.HandleFunc("/authenticate_user", authenticateUserHandler) http.HandleFunc("/clients", listHandler) http.HandleFunc("/clients/", clientHandler) http.HandleFunc("/cookbooks", cookbookHandler) http.HandleFunc("/cookbooks/", cookbookHandler) http.HandleFunc("/data", dataHandler) http.HandleFunc("/data/", dataHandler) http.HandleFunc("/environments", environmentHandler) http.HandleFunc("/environments/", environmentHandler) http.HandleFunc("/nodes", listHandler) http.HandleFunc("/nodes/", nodeHandler) http.HandleFunc("/principals/", principalHandler) http.HandleFunc("/roles", listHandler) http.HandleFunc("/roles/", roleHandler) http.HandleFunc("/sandboxes", sandboxHandler) http.HandleFunc("/sandboxes/", sandboxHandler) http.HandleFunc("/search", searchHandler) http.HandleFunc("/search/", searchHandler) http.HandleFunc("/search/reindex", reindexHandler) http.HandleFunc("/users", listHandler) http.HandleFunc("/users/", userHandler) http.HandleFunc("/file_store/", fileStoreHandler) http.HandleFunc("/events", eventListHandler) http.HandleFunc("/events/", eventHandler) http.HandleFunc("/reports/", reportHandler) http.HandleFunc("/universe", universeHandler) http.HandleFunc("/shovey/", shoveyHandler) http.HandleFunc("/status/", statusHandler) /* TODO: figure out how to handle the root & not found pages */ http.HandleFunc("/", rootHandler) listenAddr := config.ListenAddr() var err error srv := &http.Server{Addr: listenAddr, Handler: &interceptHandler{}} if config.Config.UseSSL { srv.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS10} err = srv.ListenAndServeTLS(config.Config.SSLCert, config.Config.SSLKey) } else { err = srv.ListenAndServe() } if err != nil { logger.Criticalf("ListenAndServe: %s", err.Error()) os.Exit(1) } }