Mercurial > gemma
view cmd/gemma/root.go @ 221:696c19abe869
Argh! If one is using its own storage for config like we do
the config loaded by viper needs to be injected back into
cobra [https://github.com/spf13/cobra/issues/367].
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Tue, 24 Jul 2018 18:21:31 +0200 |
parents | 11d1a488b08f |
children | 63dd5216eee4 |
line wrap: on
line source
package main import ( "context" "fmt" "log" "net/http" "os" "os/signal" "path/filepath" "syscall" "gemma.intevation.de/gemma/auth" "gemma.intevation.de/gemma/config" homedir "github.com/mitchellh/go-homedir" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" ) var rootCmd = &cobra.Command{ Use: "gemma", Short: "gemma is a server for waterway monitoring and management", Run: start, } // This is not part of the persistent config. var configFile string func init() { cobra.OnInitialize(initConfig) fl := rootCmd.PersistentFlags fl().StringVarP(&configFile, "config", "c", "", "config file (default is $HOME/.gemma.toml)") fl().StringVarP(&config.Config.DBHost, "dbhost", "H", "localhost", "host of the database") fl().UintVarP(&config.Config.DBPort, "dbport", "P", 5432, "port of the database") fl().StringVarP(&config.Config.DBName, "dbname", "d", "gemma", "name of the database") fl().StringVarP(&config.Config.DBSSLMode, "dbssl", "S", "require", "SSL mode of the database") fl().StringVarP(&config.Config.SessionStore, "sessions", "s", "", "path to the sessions file") fl().StringVarP(&config.Config.Web, "web", "w", "", "path to the web files") fl().StringVarP(&config.Config.WebHost, "host", "o", "localhost", "host of the web app") fl().UintVarP(&config.Config.WebPort, "port", "p", 8000, "port of the web app") viper.BindPFlag("dbhost", fl().Lookup("dbhost")) viper.BindPFlag("dbport", fl().Lookup("dbport")) viper.BindPFlag("dbname", fl().Lookup("dbname")) viper.BindPFlag("dbssl", fl().Lookup("dbssl")) viper.BindPFlag("sessions", fl().Lookup("sessions")) viper.BindPFlag("web", fl().Lookup("web")) viper.BindPFlag("host", fl().Lookup("host")) viper.BindPFlag("port", fl().Lookup("port")) } func initConfig() { // Don't forget to read config either from cfgFile or from home directory! if configFile != "" { // Use config file from the flag. viper.SetConfigFile(configFile) } else { // Find home directory. home, err := homedir.Dir() if err != nil { fmt.Println(err) os.Exit(1) } // Search config in home directory with name ".cobra" (without extension). viper.AddConfigPath(home) viper.SetConfigName(".gemma") } if err := viper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok && configFile == "" { // Don't bother if not found. return } log.Fatalf("Can't read config: %v\n", err) } } func injectViper(cmd *cobra.Command) { cmd.Flags().VisitAll(func(f *pflag.Flag) { if !f.Changed { if viper.IsSet(f.Name) { cmd.Flags().Set(f.Name, viper.GetString(f.Name)) } } }) } func start(cmd *cobra.Command, args []string) { // XXX: This hack is needed because we have our // own config storage. injectViper(cmd) // Install connection pool cp, err := auth.NewConnectionPool(config.Config.SessionStore) if err != nil { log.Fatalf("Error with session store: %v\n", err) } auth.ConnPool = cp p, err := filepath.Abs(config.Config.Web) if err != nil { log.Fatalf("error: %v\n", err) } mux := http.NewServeMux() mux.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir(p)))) mux.HandleFunc("/api/token", token) mux.Handle("/api/logout", auth.SessionMiddleware(http.HandlerFunc(token))) mux.Handle("/api/renew", auth.SessionMiddleware(http.HandlerFunc(renew))) mux.Handle("/api/create_user", auth.SessionMiddleware( auth.SessionChecker(http.HandlerFunc(createUser), auth.HasRole("sys_admin")))) addr := fmt.Sprintf("%s:%d", config.Config.WebHost, config.Config.WebPort) log.Printf("listen on %s\n", addr) server := http.Server{Addr: addr, Handler: mux} done := make(chan error) go func() { defer close(done) done <- server.ListenAndServe() }() sigChan := make(chan os.Signal) signal.Notify(sigChan, os.Interrupt, os.Kill, syscall.SIGTERM) select { case err := <-done: if err != nil && err != http.ErrServerClosed { log.Fatalf("error: %v\n", err) } case <-sigChan: } server.Shutdown(context.Background()) <-done if err := auth.ConnPool.Shutdown(); err != nil { log.Fatalf("error: %v\n", err) } }