// StartSerfin sets up the serf instance and starts listening for events and // queries from other serf instances. func StartSerfin() error { var err error Serfer, err = serfclient.NewRPCClient(config.Config.SerfAddr) if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } if config.Config.SerfEventAnnounce { err = Serfer.UserEvent("goiardi-join", []byte(config.Config.Hostname), true) if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } } return nil }
func AllShoveyRuns() []*ShoveyRun { var shoveyRuns []*ShoveyRun shoveys := AllShoveys() for _, s := range shoveys { runs, err := s.GetNodeRuns() if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } shoveyRuns = append(shoveyRuns, runs...) } return shoveyRuns }
// AllNodeStatuses returns all node status reports on the server, from all // nodes. func AllNodeStatuses() []*NodeStatus { var allStatus []*NodeStatus nodes := AllNodes() for _, n := range nodes { ns, err := n.AllStatuses() if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } allStatus = append(allStatus, ns...) } return allStatus }
func AllShoveyRunStreams() []*ShoveyRunStream { var streams []*ShoveyRunStream shoveyRuns := AllShoveyRuns() outputTypes := []string{"stdout", "stderr"} for _, sr := range shoveyRuns { for _, t := range outputTypes { srs, err := sr.GetStreamOutput(t, 0) if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } streams = append(streams, srs...) } } return streams }
// AllShoveys returns all shovey objects on the server func AllShoveys() []*Shovey { var shoveys []*Shovey if config.UsingDB() { return allShoveysSQL() } shoveList := GetList() for _, s := range shoveList { sh, err := Get(s) if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } shoveys = append(shoveys, sh) } return shoveys }
func main() { if setting.Config.ExpvarAddr != "" { go func() { err := http.ListenAndServe(setting.Config.ExpvarAddr, nil) if err != nil { fmt.Println("Error starting expvar http listener:", err.Error()) os.Exit(1) } }() } // First fire up a queue to consume metric def events mdConn, err := amqp.Dial(setting.Config.RabbitMQURL) if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } defer mdConn.Close() logger.Debugf("connected") done := make(chan error, 1) var numCPU int if setting.Config.NumWorkers != 0 { numCPU = setting.Config.NumWorkers } else { numCPU = runtime.NumCPU() } err = qproc.ProcessQueue(mdConn, "metrics", "topic", "", "metrics.*", false, true, true, done, processMetricDefEvent, numCPU) if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } err = qproc.ProcessQueue(mdConn, "metricResults", "x-consistent-hash", "", "10", false, true, true, done, processMetrics, numCPU) if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } err = initEventProcessing(mdConn, numCPU, done) if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } // Signal handling. If SIGQUIT is received, print out the current // stack. Otherwise if SIGINT or SIGTERM are received clean up and exit // in an orderly fashion. go func() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGQUIT, os.Interrupt, syscall.SIGTERM) buf := make([]byte, 1<<20) for sig := range sigs { if sig == syscall.SIGQUIT { // print out the current stack on SIGQUIT runtime.Stack(buf, true) log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf) } else { // finish our existing work, clean up, and exit // in an orderly fashion logger.Infof("Closing rabbitmq connection") cerr := mdConn.Close() if cerr != nil { logger.Errorf("Received error closing rabbitmq connection: %s", cerr.Error()) } logger.Infof("Closing processing buffer channel") close(bufCh) } } }() // this channel returns when one of the workers exits. err = <-done logger.Criticalf("all done!", err) if err != nil { logger.Criticalf("Had an error, aiiieeee! '%s'", err.Error()) } }
// ParseConfigOptions reads and applies arguments from the command line and the // configuration file, merging them together as needed, with command line options // taking precedence over options in the config file. func ParseConfigOptions() error { var opts = &Options{} _, err := flags.Parse(opts) if err != nil { if err.(*flags.Error).Type == flags.ErrHelp { os.Exit(0) } else { log.Println(err) os.Exit(1) } } if opts.Version { fmt.Printf("goiardi version %s (aiming for compatibility with Chef Server version %s).\n", Version, ChefVersion) os.Exit(0) } /* Load the config file. Command-line options have precedence over * config file options. */ if opts.ConfFile != "" { if _, err := toml.DecodeFile(opts.ConfFile, Config); err != nil { log.Println(err) os.Exit(1) } Config.ConfFile = opts.ConfFile Config.FreezeData = false } if opts.Export != "" && opts.Import != "" { log.Println("Cannot use -x/--export and -m/--import flags together.") os.Exit(1) } if opts.Export != "" { Config.DoExport = true Config.ImpExFile = opts.Export } else if opts.Import != "" { Config.DoImport = true Config.ImpExFile = opts.Import } if opts.Hostname != "" { Config.Hostname = opts.Hostname } else { if Config.Hostname == "" { Config.Hostname, err = os.Hostname() if err != nil { log.Println(err) Config.Hostname = "localhost" } } } if opts.DataStoreFile != "" { Config.DataStoreFile = opts.DataStoreFile } if opts.IndexFile != "" { Config.IndexFile = opts.IndexFile } // Use MySQL? if opts.UseMySQL { Config.UseMySQL = opts.UseMySQL } // Use Postgres? if opts.UsePostgreSQL { Config.UsePostgreSQL = opts.UsePostgreSQL } if Config.UseMySQL && Config.UsePostgreSQL { err := fmt.Errorf("The MySQL and Postgres options cannot be used together.") log.Println(err) os.Exit(1) } if Config.DataStoreFile != "" && (Config.UseMySQL || Config.UsePostgreSQL) { err := fmt.Errorf("The MySQL or Postgres and data store options may not be specified together.") log.Println(err) os.Exit(1) } if !((Config.DataStoreFile == "" && Config.IndexFile == "") || ((Config.DataStoreFile != "" || (Config.UseMySQL || Config.UsePostgreSQL)) && Config.IndexFile != "")) { err := fmt.Errorf("-i and -D must either both be specified, or not specified") log.Println(err) os.Exit(1) } if (Config.UseMySQL || Config.UsePostgreSQL) && Config.IndexFile == "" { err := fmt.Errorf("An index file must be specified with -i or --index-file (or the 'index-file' config file option) when running with a MySQL or PostgreSQL backend.") log.Println(err) os.Exit(1) } if Config.IndexFile != "" && (Config.DataStoreFile != "" || (Config.UseMySQL || Config.UsePostgreSQL)) { Config.FreezeData = true } if opts.LogFile != "" { Config.LogFile = opts.LogFile } if opts.SysLog { Config.SysLog = opts.SysLog } if Config.LogFile != "" { lfp, lerr := os.Create(Config.LogFile) if lerr != nil { log.Println(err) os.Exit(1) } log.SetOutput(lfp) } if dlev := len(opts.Verbose); dlev != 0 { Config.DebugLevel = dlev } if Config.LogLevel != "" { if lev, ok := LogLevelNames[strings.ToLower(Config.LogLevel)]; ok && Config.DebugLevel == 0 { Config.DebugLevel = lev } } if Config.DebugLevel > 4 { Config.DebugLevel = 4 } Config.DebugLevel = int(logger.LevelCritical) - Config.DebugLevel logger.SetLevel(logger.LogLevel(Config.DebugLevel)) debugLevel := map[int]string{0: "debug", 1: "info", 2: "warning", 3: "error", 4: "critical"} log.Printf("Logging at %s level", debugLevel[Config.DebugLevel]) if Config.SysLog { sl, err := logger.NewSysLogger("goiardi") if err != nil { log.Println(err.Error()) os.Exit(1) } logger.SetLogger(sl) } else { logger.SetLogger(logger.NewGoLogger()) } /* Database options */ // Don't bother setting a default mysql port if mysql isn't used if Config.UseMySQL { if Config.MySQL.Port == "" { Config.MySQL.Port = "3306" } } // set default Postgres options if Config.UsePostgreSQL { if Config.PostgreSQL.Port == "" { Config.PostgreSQL.Port = "5432" } } if opts.LocalFstoreDir != "" { Config.LocalFstoreDir = opts.LocalFstoreDir } if Config.LocalFstoreDir == "" && (Config.UseMySQL || Config.UsePostgreSQL) { logger.Criticalf("local-filestore-dir must be set when running goiardi in SQL mode") os.Exit(1) } if !Config.FreezeData && (opts.FreezeInterval != 0 || Config.FreezeInterval != 0) { logger.Warningf("FYI, setting the freeze data interval's not especially useful without setting the index and data files.") } if opts.FreezeInterval != 0 { Config.FreezeInterval = opts.FreezeInterval } if Config.FreezeInterval == 0 { Config.FreezeInterval = 300 } /* Root directory for certs and the like */ if opts.ConfRoot != "" { Config.ConfRoot = opts.ConfRoot } if Config.ConfRoot == "" { if Config.ConfFile != "" { Config.ConfRoot = path.Dir(Config.ConfFile) } else { Config.ConfRoot = "." } } Config.Ipaddress = opts.Ipaddress if opts.Port != 0 { Config.Port = opts.Port } if Config.Port == 0 { Config.Port = 4545 } if opts.UseSSL { Config.UseSSL = opts.UseSSL } if opts.SSLCert != "" { Config.SSLCert = opts.SSLCert } if opts.SSLKey != "" { Config.SSLKey = opts.SSLKey } if opts.HTTPSUrls { Config.HTTPSUrls = opts.HTTPSUrls } // SSL setup if Config.Port == 80 { Config.UseSSL = false } else if Config.Port == 443 { Config.UseSSL = true } if Config.UseSSL { if Config.SSLCert == "" || Config.SSLKey == "" { logger.Criticalf("SSL mode requires specifying both a certificate and a key file.") os.Exit(1) } /* If the SSL cert and key are not absolute files, join them * with the conf root */ if !path.IsAbs(Config.SSLCert) { Config.SSLCert = path.Join(Config.ConfRoot, Config.SSLCert) } if !path.IsAbs(Config.SSLKey) { Config.SSLKey = path.Join(Config.ConfRoot, Config.SSLKey) } } if opts.TimeSlew != "" { Config.TimeSlew = opts.TimeSlew } if Config.TimeSlew != "" { d, derr := time.ParseDuration(Config.TimeSlew) if derr != nil { logger.Criticalf("Error parsing time-slew: %s", derr.Error()) os.Exit(1) } Config.TimeSlewDur = d } else { Config.TimeSlewDur, _ = time.ParseDuration("15m") } if opts.UseAuth { Config.UseAuth = opts.UseAuth } if opts.DisableWebUI { Config.DisableWebUI = opts.DisableWebUI } if opts.LogEvents { Config.LogEvents = opts.LogEvents } if opts.LogEventKeep != 0 { Config.LogEventKeep = opts.LogEventKeep } // Set max sizes for objects and json requests. if opts.ObjMaxSize != 0 { Config.ObjMaxSize = opts.ObjMaxSize } if opts.JSONReqMaxSize != 0 { Config.JSONReqMaxSize = opts.JSONReqMaxSize } if Config.ObjMaxSize == 0 { Config.ObjMaxSize = 10485760 } if Config.JSONReqMaxSize == 0 { Config.JSONReqMaxSize = 1000000 } if opts.UseUnsafeMemStore { Config.UseUnsafeMemStore = opts.UseUnsafeMemStore } return nil }
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() 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(config.Config.IndexFile) 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(config.Config.IndexFile); err != nil { logger.Errorf(err.Error()) } } if config.UsingDB() { datastore.Dbh.Close() } fmt.Println("All done.") os.Exit(0) } /* 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) /* TODO: figure out how to handle the root & not found pages */ http.HandleFunc("/", rootHandler) listenAddr := config.ListenAddr() var err error if config.Config.UseSSL { err = http.ListenAndServeTLS(listenAddr, config.Config.SSLCert, config.Config.SSLKey, &interceptHandler{}) } else { err = http.ListenAndServe(listenAddr, &interceptHandler{}) } if err != nil { logger.Criticalf("ListenAndServe: %s", err.Error()) os.Exit(1) } }
func createDefaultActors() { if cwebui, _ := client.Get("chef-webui"); cwebui == nil { if webui, nerr := client.New("chef-webui"); nerr != nil { logger.Criticalf(nerr.Error()) os.Exit(1) } else { webui.Admin = true pem, err := webui.GenerateKeys() if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } if config.Config.UseAuth { if fp, ferr := os.Create(fmt.Sprintf("%s/%s.pem", config.Config.ConfRoot, webui.Name)); ferr == nil { fp.Chmod(0600) fp.WriteString(pem) fp.Close() } else { logger.Criticalf(ferr.Error()) os.Exit(1) } } webui.Save() } } if cvalid, _ := client.Get("chef-validator"); cvalid == nil { if validator, verr := client.New("chef-validator"); verr != nil { logger.Criticalf(verr.Error()) os.Exit(1) } else { validator.Validator = true pem, err := validator.GenerateKeys() if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } if config.Config.UseAuth { if fp, ferr := os.Create(fmt.Sprintf("%s/%s.pem", config.Config.ConfRoot, validator.Name)); ferr == nil { fp.Chmod(0600) fp.WriteString(pem) fp.Close() } else { logger.Criticalf(ferr.Error()) os.Exit(1) } } validator.Save() } } if uadmin, _ := user.Get("admin"); uadmin == nil { if admin, aerr := user.New("admin"); aerr != nil { logger.Criticalf(aerr.Error()) os.Exit(1) } else { admin.Admin = true pem, err := admin.GenerateKeys() if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } if config.Config.UseAuth { if fp, ferr := os.Create(fmt.Sprintf("%s/%s.pem", config.Config.ConfRoot, admin.Name)); ferr == nil { fp.Chmod(0600) fp.WriteString(pem) fp.Close() } else { logger.Criticalf(ferr.Error()) os.Exit(1) } } if aerr := admin.Save(); aerr != nil { logger.Criticalf(aerr.Error()) os.Exit(1) } } } environment.MakeDefaultEnvironment() return }
// ParseConfigOptions reads and applies arguments from the command line and the // configuration file, merging them together as needed, with command line options // taking precedence over options in the config file. func ParseConfigOptions() error { var opts = &Options{} _, err := flags.Parse(opts) if err != nil { if err.(*flags.Error).Type == flags.ErrHelp { os.Exit(0) } else { log.Println(err) os.Exit(1) } } if opts.Version { fmt.Printf("goiardi version %s (aiming for compatibility with Chef Server version %s).\n", Version, ChefVersion) os.Exit(0) } /* Load the config file. Command-line options have precedence over * config file options. */ if opts.ConfFile != "" { if _, err := toml.DecodeFile(opts.ConfFile, Config); err != nil { log.Println(err) os.Exit(1) } Config.ConfFile = opts.ConfFile Config.FreezeData = false } if opts.Export != "" && opts.Import != "" { log.Println("Cannot use -x/--export and -m/--import flags together.") os.Exit(1) } if opts.Export != "" { Config.DoExport = true Config.ImpExFile = opts.Export } else if opts.Import != "" { Config.DoImport = true Config.ImpExFile = opts.Import } if opts.Hostname != "" { Config.Hostname = opts.Hostname } else { if Config.Hostname == "" { Config.Hostname, err = os.Hostname() if err != nil { log.Println(err) Config.Hostname = "localhost" } } } if opts.DataStoreFile != "" { Config.DataStoreFile = opts.DataStoreFile } if opts.IndexFile != "" { Config.IndexFile = opts.IndexFile } // Use MySQL? if opts.UseMySQL { Config.UseMySQL = opts.UseMySQL } // Use Postgres? if opts.UsePostgreSQL { Config.UsePostgreSQL = opts.UsePostgreSQL } if Config.UseMySQL && Config.UsePostgreSQL { err := fmt.Errorf("The MySQL and Postgres options cannot be used together.") log.Println(err) os.Exit(1) } // Use Postgres search? if opts.PgSearch { // make sure postgres is enabled if !Config.UsePostgreSQL { err := fmt.Errorf("--pg-search requires --use-postgresql (which makes sense, really).") log.Println(err) os.Exit(1) } Config.PgSearch = opts.PgSearch } if Config.DataStoreFile != "" && (Config.UseMySQL || Config.UsePostgreSQL) { err := fmt.Errorf("The MySQL or Postgres and data store options may not be specified together.") log.Println(err) os.Exit(1) } if !((Config.DataStoreFile == "" && Config.IndexFile == "") || ((Config.DataStoreFile != "" || (Config.UseMySQL || Config.UsePostgreSQL)) && Config.IndexFile != "")) { err := fmt.Errorf("-i and -D must either both be specified, or not specified") log.Println(err) os.Exit(1) } if (Config.UseMySQL || Config.UsePostgreSQL) && (Config.IndexFile == "" && !Config.PgSearch) { err := fmt.Errorf("An index file must be specified with -i or --index-file (or the 'index-file' config file option) when running with a MySQL or PostgreSQL backend.") log.Println(err) os.Exit(1) } if Config.IndexFile != "" && (Config.DataStoreFile != "" || (Config.UseMySQL || Config.UsePostgreSQL)) { Config.FreezeData = true } if opts.LogFile != "" { Config.LogFile = opts.LogFile } if opts.SysLog { Config.SysLog = opts.SysLog } if Config.LogFile != "" { lfp, lerr := os.Create(Config.LogFile) if lerr != nil { log.Println(err) os.Exit(1) } log.SetOutput(lfp) } if dlev := len(opts.Verbose); dlev != 0 { Config.DebugLevel = dlev } if Config.LogLevel != "" { if lev, ok := LogLevelNames[strings.ToLower(Config.LogLevel)]; ok && Config.DebugLevel == 0 { Config.DebugLevel = lev } } if Config.DebugLevel > 4 { Config.DebugLevel = 4 } Config.DebugLevel = int(logger.LevelCritical) - Config.DebugLevel logger.SetLevel(logger.LogLevel(Config.DebugLevel)) debugLevel := map[int]string{0: "debug", 1: "info", 2: "warning", 3: "error", 4: "critical"} log.Printf("Logging at %s level", debugLevel[Config.DebugLevel]) if Config.SysLog { sl, err := logger.NewSysLogger("goiardi") if err != nil { log.Println(err.Error()) os.Exit(1) } logger.SetLogger(sl) } else { logger.SetLogger(logger.NewGoLogger()) } /* Database options */ // Don't bother setting a default mysql port if mysql isn't used if Config.UseMySQL { if Config.MySQL.Port == "" { Config.MySQL.Port = "3306" } } // set default Postgres options if Config.UsePostgreSQL { if Config.PostgreSQL.Port == "" { Config.PostgreSQL.Port = "5432" } } if opts.LocalFstoreDir != "" { Config.LocalFstoreDir = opts.LocalFstoreDir } if Config.LocalFstoreDir == "" && (Config.UseMySQL || Config.UsePostgreSQL) { logger.Criticalf("local-filestore-dir must be set when running goiardi in SQL mode") os.Exit(1) } if Config.LocalFstoreDir != "" { finfo, ferr := os.Stat(Config.LocalFstoreDir) if ferr != nil { logger.Criticalf("Error checking local filestore dir: %s", ferr.Error()) os.Exit(1) } if !finfo.IsDir() { logger.Criticalf("Local filestore dir %s is not a directory", Config.LocalFstoreDir) os.Exit(1) } } if !Config.FreezeData && (opts.FreezeInterval != 0 || Config.FreezeInterval != 0) { logger.Warningf("FYI, setting the freeze data interval's not especially useful without setting the index and data files.") } if opts.FreezeInterval != 0 { Config.FreezeInterval = opts.FreezeInterval } if Config.FreezeInterval == 0 { Config.FreezeInterval = 10 } /* Root directory for certs and the like */ if opts.ConfRoot != "" { Config.ConfRoot = opts.ConfRoot } if Config.ConfRoot == "" { if Config.ConfFile != "" { Config.ConfRoot = path.Dir(Config.ConfFile) } else { Config.ConfRoot = "." } } Config.Ipaddress = opts.Ipaddress if Config.Ipaddress != "" { ip := net.ParseIP(Config.Ipaddress) if ip == nil { logger.Criticalf("IP address '%s' is not valid", Config.Ipaddress) os.Exit(1) } } if opts.Port != 0 { Config.Port = opts.Port } if Config.Port == 0 { Config.Port = 4545 } if opts.UseSSL { Config.UseSSL = opts.UseSSL } if opts.SSLCert != "" { Config.SSLCert = opts.SSLCert } if opts.SSLKey != "" { Config.SSLKey = opts.SSLKey } if opts.HTTPSUrls { Config.HTTPSUrls = opts.HTTPSUrls } // SSL setup if Config.Port == 80 { Config.UseSSL = false } else if Config.Port == 443 { Config.UseSSL = true } if Config.UseSSL { if Config.SSLCert == "" || Config.SSLKey == "" { logger.Criticalf("SSL mode requires specifying both a certificate and a key file.") os.Exit(1) } /* If the SSL cert and key are not absolute files, join them * with the conf root */ if !path.IsAbs(Config.SSLCert) { Config.SSLCert = path.Join(Config.ConfRoot, Config.SSLCert) } if !path.IsAbs(Config.SSLKey) { Config.SSLKey = path.Join(Config.ConfRoot, Config.SSLKey) } } if opts.TimeSlew != "" { Config.TimeSlew = opts.TimeSlew } if Config.TimeSlew != "" { d, derr := time.ParseDuration(Config.TimeSlew) if derr != nil { logger.Criticalf("Error parsing time-slew: %s", derr.Error()) os.Exit(1) } Config.TimeSlewDur = d } else { Config.TimeSlewDur, _ = time.ParseDuration("15m") } if opts.UseAuth { Config.UseAuth = opts.UseAuth } if opts.DisableWebUI { Config.DisableWebUI = opts.DisableWebUI } if opts.LogEvents { Config.LogEvents = opts.LogEvents } if opts.LogEventKeep != 0 { Config.LogEventKeep = opts.LogEventKeep } // Set max sizes for objects and json requests. if opts.ObjMaxSize != 0 { Config.ObjMaxSize = opts.ObjMaxSize } if opts.JSONReqMaxSize != 0 { Config.JSONReqMaxSize = opts.JSONReqMaxSize } if Config.ObjMaxSize == 0 { Config.ObjMaxSize = 10485760 } if Config.JSONReqMaxSize == 0 { Config.JSONReqMaxSize = 1000000 } if opts.UseUnsafeMemStore { Config.UseUnsafeMemStore = opts.UseUnsafeMemStore } if opts.DbPoolSize != 0 { Config.DbPoolSize = opts.DbPoolSize } if opts.MaxConn != 0 { Config.MaxConn = opts.MaxConn } if !UsingDB() { if Config.DbPoolSize != 0 { logger.Infof("db-pool-size is set to %d, which is not particularly useful if you are not using one of the SQL databases.", Config.DbPoolSize) } if Config.MaxConn != 0 { logger.Infof("max-connections is set to %d, which is not particularly useful if you are not using one of the SQL databases.", Config.MaxConn) } } if opts.UseSerf { Config.UseSerf = opts.UseSerf } if Config.UseSerf { if opts.SerfAddr != "" { Config.SerfAddr = opts.SerfAddr } if Config.SerfAddr == "" { Config.SerfAddr = "127.0.0.1:7373" } } if opts.SerfEventAnnounce { Config.SerfEventAnnounce = opts.SerfEventAnnounce } if Config.SerfEventAnnounce && !Config.UseSerf { logger.Criticalf("--serf-event-announce requires --use-serf") os.Exit(1) } if opts.UseShovey { if !Config.UseSerf { logger.Criticalf("--use-shovey requires --use-serf to be enabled") os.Exit(1) } Config.UseShovey = opts.UseShovey } // shovey signing key stuff if opts.SignPrivKey != "" { Config.SignPrivKey = opts.SignPrivKey } // if using shovey, open the existing, or create if absent, signing // keys. if Config.UseShovey { if Config.SignPrivKey == "" { Config.SignPrivKey = path.Join(Config.ConfRoot, "shovey-sign_rsa") } else if !path.IsAbs(Config.SignPrivKey) { Config.SignPrivKey = path.Join(Config.ConfRoot, Config.SignPrivKey) } privfp, err := os.Open(Config.SignPrivKey) if err != nil { logger.Criticalf("Private key %s for signing shovey requests not found. Please create a set of RSA keys for this purpose.", Config.SignPrivKey) os.Exit(1) } privPem, err := ioutil.ReadAll(privfp) if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } privBlock, _ := pem.Decode(privPem) if privBlock == nil { logger.Criticalf("Invalid block size for private key for shovey") os.Exit(1) } privKey, err := x509.ParsePKCS1PrivateKey(privBlock.Bytes) if err != nil { logger.Criticalf(err.Error()) os.Exit(1) } Key.Lock() defer Key.Unlock() Key.PrivKey = privKey } if opts.DotSearch { Config.DotSearch = opts.DotSearch } else if Config.PgSearch { Config.DotSearch = true } if Config.DotSearch { if opts.ConvertSearch { Config.ConvertSearch = opts.ConvertSearch } } if Config.IndexFile != "" && Config.PgSearch { logger.Infof("Specifying an index file for search while using the postgres search isn't useful.") } return nil }