mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-07 09:05:55 +00:00
experimenting with cascading config
2 changes unrelated to cascading config: 1. using cobra.Command.RunE instead of just Run - similar behavior to log + exit, but simpler. Also prints error message, then usage, then error again which is nice. 2. getting serveCmd.Flags() once, and re-using it. More readable methinks. For cascading config, I'm trying to set things up so that we can define the flags once, and have them work from a config file, environment variable, or command line. I also don't want references to viper scattered throughout our code, so I want to set the config at startup, and not touch it from then on. The idea here is to iterate through the set up command line flags, and then set their values from viper which knows about the commmand line, the environment, and the config file, and will pick the right one. The command line flags were set pointing to the correct config values in the pilosa object, so the right values will be set automatically.
This commit is contained in:
parent
371665f459
commit
e1a582ad2c
1 changed files with 46 additions and 17 deletions
|
|
@ -6,9 +6,11 @@ import (
|
|||
"os"
|
||||
"os/signal"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/pilosa/pilosa/server"
|
||||
|
|
@ -24,22 +26,22 @@ var serveCmd = &cobra.Command{
|
|||
It will load existing data from the configured
|
||||
directory, and start listening client connections
|
||||
on the configured port.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
setupViper(cmd.Flags())
|
||||
fmt.Println(viper.AllSettings())
|
||||
serve.Server.Handler.Version = Version
|
||||
fmt.Fprintf(serve.Stderr, "Pilosa %s, build time %s\n", Version, BuildTime)
|
||||
|
||||
// Parse command line arguments.
|
||||
if err := serve.SetupConfig(args); err != nil {
|
||||
fmt.Fprintln(serve.Stderr, err)
|
||||
os.Exit(2)
|
||||
return err
|
||||
}
|
||||
|
||||
// Start CPU profiling.
|
||||
if serve.CPUProfile != "" {
|
||||
f, err := os.Create(serve.CPUProfile)
|
||||
if err != nil {
|
||||
fmt.Fprintf(serve.Stderr, "create cpu profile: %v", err)
|
||||
os.Exit(1)
|
||||
return fmt.Errorf("create cpu profile: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
|
|
@ -54,8 +56,7 @@ on the configured port.`,
|
|||
|
||||
// Execute the program.
|
||||
if err := serve.Run(); err != nil {
|
||||
fmt.Fprintln(serve.Stderr, err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
|
||||
// First SIGKILL causes server to shut down gracefully.
|
||||
|
|
@ -68,22 +69,50 @@ on the configured port.`,
|
|||
go func() { <-c; os.Exit(1) }()
|
||||
|
||||
if err := serve.Close(); err != nil {
|
||||
fmt.Fprintln(serve.Stderr, err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
serveCmd.Flags().StringVarP(&serve.ConfigPath, "config", "c", "", "Configuration file to read from")
|
||||
serveCmd.Flags().StringVarP(&serve.CPUProfile, "cpuprofile", "", "", "Where to store CPU profile")
|
||||
serveCmd.Flags().DurationVarP(&serve.CPUTime, "cputime", "", 30*time.Second, "CPU profile duration")
|
||||
flags := serveCmd.Flags()
|
||||
|
||||
err := viper.BindPFlags(serveCmd.Flags())
|
||||
if err != nil {
|
||||
log.Fatalf("Error binding server flags: %v", err)
|
||||
}
|
||||
flags.StringVarP(&serve.ConfigPath, "config", "c", "", "Configuration file to read from")
|
||||
flags.StringVarP(&serve.CPUProfile, "cpu-profile", "", "", "Where to store CPU profile")
|
||||
flags.DurationVarP(&serve.CPUTime, "cpu-time", "", 30*time.Second, "CPU profile duration")
|
||||
|
||||
RootCmd.AddCommand(serveCmd)
|
||||
}
|
||||
|
||||
func setupViper(flags *flag.FlagSet) {
|
||||
// add cmd line flag def to viper
|
||||
err := viper.BindPFlags(flags)
|
||||
if err != nil {
|
||||
log.Fatalf("Error binding server flags: %v", err)
|
||||
}
|
||||
// add env to viper
|
||||
viper.SetEnvPrefix("PILOSA")
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||
viper.AutomaticEnv()
|
||||
|
||||
c := viper.GetString("config")
|
||||
|
||||
// add config file to viper
|
||||
if c != "" {
|
||||
viper.AddConfigPath(c)
|
||||
err := viper.ReadInConfig()
|
||||
if err != nil {
|
||||
log.Printf("Couldn't read config from '%s'", c)
|
||||
}
|
||||
}
|
||||
flags.VisitAll(func(f *flag.Flag) {
|
||||
log.Printf("Now visiting: %v with value '%s'", f.Name, f.Value)
|
||||
value := viper.GetString(f.Name)
|
||||
log.Printf("Setting to value: '%v'", value)
|
||||
err := f.Value.Set(value)
|
||||
if err != nil {
|
||||
log.Printf("Error setting %s to '%s': %v", f.Name, value, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue