mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
1. fixed a couple bugs with config file reading. 2. made cmd.Serve a global variable so tests could inspect it. 3. added table style testing for pilosa server 4. added the ability to stop server programmatically which also causes the cobra command running it to return.
106 lines
2.7 KiB
Go
106 lines
2.7 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
flag "github.com/spf13/pflag"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
var (
|
|
Version string
|
|
BuildTime string
|
|
)
|
|
|
|
// TODO maybe give this an Add method which will ensure two command
|
|
// with same name aren't added
|
|
var subcommandFns = map[string]func(stdin io.Reader, stdout, stderr io.Writer) *cobra.Command{}
|
|
|
|
func NewRootCommand(stdin io.Reader, stdout, stderr io.Writer) *cobra.Command {
|
|
setupVersionBuild()
|
|
rc := &cobra.Command{
|
|
Use: "pilosa",
|
|
Short: "Pilosa - A Distributed In-memory Binary Bitmap Index.",
|
|
// TODO - is documentation actually there?
|
|
Long: `Pilosa is a fast index to turbocharge your database.
|
|
|
|
This binary contains Pilosa itself, as well as common
|
|
tools for administering pilosa, importing/exporting data,
|
|
backing up, and more. Complete documentation is available
|
|
at http://pilosa.com/docs
|
|
|
|
Version: ` + Version + `
|
|
Build Time: ` + BuildTime + "\n",
|
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
|
v := viper.New()
|
|
err := setAllConfig(v, cmd.Flags(), "PILOSA")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
for _, subcomFn := range subcommandFns {
|
|
rc.AddCommand(subcomFn(stdin, stdout, stderr))
|
|
}
|
|
rc.SetOutput(stderr)
|
|
return rc
|
|
}
|
|
|
|
func setupVersionBuild() {
|
|
if Version == "" {
|
|
Version = "v0.0.0"
|
|
}
|
|
if BuildTime == "" {
|
|
BuildTime = "not recorded"
|
|
}
|
|
}
|
|
|
|
// setAllConfig takes a FlagSet to be the definition of all configuration
|
|
// options, as well as their defaults. It then reads from the command line, the
|
|
// environment, and a config file (if specified), and applies the configuration
|
|
// in that priority order. Since each flag in the set contains a pointer to
|
|
// where its value should be stored, setAllConfig can directly modify the value
|
|
// of each config variable.
|
|
//
|
|
// setAllConfig looks for environment variables which are capitalized versions
|
|
// of the flag names with dashes replaced by underscores, and prefixed with
|
|
// envPrefix plus an underscore.
|
|
func setAllConfig(v *viper.Viper, flags *flag.FlagSet, envPrefix string) error {
|
|
// add cmd line flag def to viper
|
|
err := v.BindPFlags(flags)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// add env to viper
|
|
v.SetEnvPrefix(envPrefix)
|
|
v.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
|
v.AutomaticEnv()
|
|
|
|
c := v.GetString("config")
|
|
|
|
// add config file to viper
|
|
if c != "" {
|
|
v.SetConfigFile(c)
|
|
v.SetConfigType("toml")
|
|
err := v.ReadInConfig()
|
|
if err != nil {
|
|
return fmt.Errorf("error reading configuration file '%s': %v", c, err)
|
|
}
|
|
}
|
|
|
|
// set all values from viper
|
|
var flagErr error
|
|
flags.VisitAll(func(f *flag.Flag) {
|
|
if flagErr != nil {
|
|
return
|
|
}
|
|
value := v.GetString(f.Name)
|
|
flagErr = f.Value.Set(value)
|
|
})
|
|
return flagErr
|
|
}
|