Mercurial > gemma
view cmd/gemma/root.go @ 226:63dd5216eee4
Refactored gemma server to be more REST-like.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Thu, 26 Jul 2018 12:24:30 +0200 |
parents | 696c19abe869 |
children | c2334b5d3dd0 |
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" "gemma.intevation.de/gemma/controllers" "github.com/gorilla/mux" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" homedir "github.com/mitchellh/go-homedir" ) 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 prepareConnectionPool() { // 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 } 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) web, err := filepath.Abs(config.Config.Web) if err != nil { log.Fatalf("error: %v\n", err) } prepareConnectionPool() m := mux.NewRouter() controllers.BindRoutes(m) m.PathPrefix("/").Handler(http.FileServer(http.Dir(web))) addr := fmt.Sprintf("%s:%d", config.Config.WebHost, config.Config.WebPort) log.Printf("listen on %s\n", addr) server := http.Server{Addr: addr, Handler: m} 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) } }