Mercurial > gemma
changeset 220:11d1a488b08f
Depend command line parsing on Viper/Cobra. Configuration should be persistent now.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Tue, 24 Jul 2018 17:45:17 +0200 |
parents | ddc78991edbc |
children | 696c19abe869 |
files | 3rdpartylibs.sh auth/connection.go auth/pool.go cmd/gemma/main.go cmd/gemma/root.go config/config.go |
diffstat | 6 files changed, 143 insertions(+), 106 deletions(-) [+] |
line wrap: on
line diff
--- a/3rdpartylibs.sh Tue Jul 24 16:19:05 2018 +0200 +++ b/3rdpartylibs.sh Tue Jul 24 17:45:17 2018 +0200 @@ -1,3 +1,6 @@ #!/bin/sh go get -u -v github.com/jackc/pgx go get -u -v github.com/coreos/bbolt/... +go get -u -v github.com/mitchellh/go-homedir +go get -u -v github.com/spf13/cobra +go get -u -v github.com/spf13/viper
--- a/auth/connection.go Tue Jul 24 16:19:05 2018 +0200 +++ b/auth/connection.go Tue Jul 24 17:45:17 2018 +0200 @@ -7,20 +7,10 @@ "log" "sync" "time" - - "gemma.intevation.de/gemma/config" ) var ErrNoSuchToken = errors.New("No such token") -var ConnPool = func() *ConnectionPool { - cp, err := NewConnectionPool(config.Config.SessionStore) - if err != nil { - log.Panicf("Error with session store: %v\n", err) - } - return cp -}() - const ( maxOpen = 16 maxDBIdle = time.Minute * 5
--- a/auth/pool.go Tue Jul 24 16:19:05 2018 +0200 +++ b/auth/pool.go Tue Jul 24 17:45:17 2018 +0200 @@ -9,6 +9,9 @@ bolt "github.com/coreos/bbolt" ) +// ConnPool is the global connection pool. +var ConnPool *ConnectionPool + type ConnectionPool struct { storage *bolt.DB conns map[string]*Connection
--- a/cmd/gemma/main.go Tue Jul 24 16:19:05 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - "log" - "net/http" - "os" - "os/signal" - "path/filepath" - "syscall" - - "gemma.intevation.de/gemma/auth" -) - -func main() { - port := flag.Int("port", 8000, "port to listen at.") - host := flag.String("host", "localhost", "host to listen at.") - flag.Parse() - p, _ := filepath.Abs("./web") - 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", *host, *port) - - 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) - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmd/gemma/root.go Tue Jul 24 17:45:17 2018 +0200 @@ -0,0 +1,132 @@ +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/viper" +) + +var rootCmd = &cobra.Command{ + Use: "gemma", + Short: "gemma is a server for waterway monitoring and management", + Run: start, +} + +func init() { + cobra.OnInitialize(initConfig) + fl := rootCmd.PersistentFlags + fl().StringVarP(&config.Config.File, "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 config.Config.File != "" { + // Use config file from the flag. + viper.SetConfigFile(config.Config.File) + } 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 { + // Don't bother if not found. + return + } + log.Fatalf("Can't read config: %v\n", err) + } +} + +func start(cmd *cobra.Command, args []string) { + + // 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) + } + log.Printf("web: %s\n", p) + 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) + } +}
--- a/config/config.go Tue Jul 24 16:19:05 2018 +0200 +++ b/config/config.go Tue Jul 24 17:45:17 2018 +0200 @@ -1,48 +1,17 @@ package config -import ( - "log" - "os" - "strconv" -) - -var Config = NewConfiguration() +var Config Configuration type Configuration struct { + File string DBHost string DBPort uint DBName string DBSSLMode string SessionStore string -} -func NewConfiguration() *Configuration { - // TODO: Load from file. - return &Configuration{ - DBHost: envString("GEMMA_DB_HOST", "localhost"), - DBPort: envUint("GEMMA_DB_PORT", 5432), - DBName: envString("GEMMA_DB_NAME", "gemma"), - DBSSLMode: envString("GEMMA_DB_SSL_MODE", "require"), - SessionStore: envString("GEMMA_SESSION_STORE", ""), - } + Web string + WebHost string + WebPort uint } - -func envString(key, def string) string { - if v, ok := os.LookupEnv(key); ok { - return v - } - return def -} - -func envUint(key string, def uint) uint { - if v, ok := os.LookupEnv(key); ok { - x, err := strconv.ParseUint(v, 10, 64) - if err != nil { - log.Printf("warn: invalid uint env %s: %v\n", key, err) - return def - } - return uint(x) - } - return def -}