diff --git a/client/config/config.go b/client/config/config.go index 3d9594f587ad..cb66efa2bf94 100644 --- a/client/config/config.go +++ b/client/config/config.go @@ -3,15 +3,17 @@ package config import ( "fmt" "io" - "io/ioutil" "os" - "path" "strconv" + "errors" + toml "github.com/pelletier/go-toml" "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/cosmos/cosmos-sdk/client/flags" ) @@ -50,48 +52,35 @@ config keyring-backend with no arguments // outputs default config invalidKey invalidValue -CLI flags - -do i need to add all flags? from client/flags/flags.go - -"keyring-dir" : "", -"ledger": false, -"height": 0, -"gas-adjustment": flags.DefaultGasAdjustment,//float -"from": "", -"account-number": 0, -"sequence": 0, -"memo": "", -"fees": "", -"gas-prices":"", -"dry-run": false, -"generate-only":false, -"offline": false, -"yes": true, //doublec heck skip-confirmation = true - - - - +*/ +var ErrWrongNumberOfArgs = fmt.Errorf("wrong number of arguments") +type ClientConfig struct{ -*/ + ChainID string `mapstructure:"chain-id"` + KeyringBackend string `mapstructure:"keyring-backend"` + Output string `mapstructure:"output"` + Node string `mapstructure:"node"` + BroadcastMode string `mapstructure:"broadcast-mode"` + Trace bool `mapstructure:"trace"` +} -var ErrWrongNumberOfArgs = fmt.Errorf("wrong number of arguments") +func DefaultClientConfig() *ClientConfig { + return &ClientConfig{ + ChainID : "", + KeyringBackend :"os", + Output : "text", + Node: "tcp://localhost:26657", + BroadcastMode : "sync", + Trace : false, + } +} -// is this full client side configuration? -// add height = 0 -var configDefaults = map[string]string{ - "chain-id": "", - "keyring-backend": "os", - "output": "text", - "node": "tcp://localhost:26657", - "broadcast-mode": "sync", -} -// ConfigCmd returns a CLI command to interactively create an application CLI +// Cmd returns a CLI command to interactively create an application CLI // config file. func Cmd(defaultCLIHome string) *cobra.Command { cmd := &cobra.Command{ @@ -108,6 +97,98 @@ func Cmd(defaultCLIHome string) *cobra.Command { return cmd } +func runConfigCmd(cmd *cobra.Command, args []string) error { + + + InitConfigTemplate() + + cfgPath, err := ensureConfFile(viper.GetString(flags.FlagHome)) + if err != nil { + return err + } + + getAction := viper.GetBool(flagGet) + if getAction && len(args) != 1 { + return ErrWrongNumberOfArgs + } + + cliConfig, err := getClientConfig(cfgPath) + if err != nil { + return fmt.Errorf("Unable to get client config %v", err) + } + + + switch len(args) { + case 0: + // print all client config fields to sdt out + // TODO implement method to print out all client config fiels + fmt.Println(cliConfig.ChainID) + fmt.Println(cliConfig.KeyringBackend) + fmt.Println(cliConfig.Output) + fmt.Println(cliConfig.Node) + fmt.Println(cliConfig.BroadcastMode) + fmt.Println(cliConfig.Trace) + + case 1: + // it's a get + // TODO implement method for get + key := args[0] + switch key { + case "chain-id": fmt.Println(cliConfig.ChainID) + case "keyring-backend": fmt.Println(cliConfig.KeyringBackend) + case "output": fmt.Println(cliConfig.Output) + case "node": fmt.Println(cliConfig.Node) + case "broadcast-mode": fmt.Println(cliConfig.BroadcastMode) + case "trace": fmt.Println(cliConfig.Trace) + default : + return errUnknownConfigKey(key) + } + + case 2: + // it's set + // TODO impement method for set + // TODO implement setters + key, value := args[0], args[1] + switch key { + case "chain-id": cliConfig.ChainID = value + case "keyring-backend": cliConfig.KeyringBackend = value + case "output": cliConfig.Output = value + case "node": cliConfig.Node = value + case "broadcast-mode": cliConfig.BroadcastMode = value + case "trace": + boolVal, err := strconv.ParseBool(value) + if err != nil { + return err + } + cliConfig.Trace = boolVal + default : + return errUnknownConfigKey(key) + } + + default: + // print error + return errors.New("Unknown configuration error") + } + + + WriteConfigFile() + + + + return nil + + + + + + + + +} + + + +/* func runConfigCmd(cmd *cobra.Command, args []string) error { cfgFile, err := ensureConfFile(viper.GetString(flags.FlagHome)) if err != nil { @@ -143,6 +224,9 @@ func runConfigCmd(cmd *cobra.Command, args []string) error { case "chain-id", "keyring-backend", "output", "node", "broadcast-mode": fmt.Println(tree.Get(key).(string)) + case "trace": + fmt.Println(tree.Get(key).(bool)) + default: // do we need to print out default value here in case key is invalid? if defaultValue, ok := configDefaults[key]; ok { @@ -168,8 +252,7 @@ func runConfigCmd(cmd *cobra.Command, args []string) error { case "chain-id", "keyring-backend", "output", "node", "broadcast-mode": tree.Set(key, value) - // do we need to check if key matches one of these? - case "trace", "trust-node", "indent": + case "trace": boolVal, err := strconv.ParseBool(value) if err != nil { return err @@ -189,16 +272,10 @@ func runConfigCmd(cmd *cobra.Command, args []string) error { fmt.Fprintf(os.Stderr, "configuration saved to %s\n", cfgFile) return nil } +*/ -func ensureConfFile(rootDir string) (string, error) { - cfgPath := path.Join(rootDir, "config") - if err := os.MkdirAll(cfgPath, os.ModePerm); err != nil { // config directory - return "", err - } - - return path.Join(cfgPath, "client.toml"), nil -} +/* func loadConfigFile(cfgFile string) (*toml.Tree, error) { if _, err := os.Stat(cfgFile); os.IsNotExist(err) { fmt.Fprintf(os.Stderr, "%s does not exist\n", cfgFile) @@ -217,6 +294,7 @@ func loadConfigFile(cfgFile string) (*toml.Tree, error) { return tree, nil } +*/ func saveConfigFile(cfgFile string, tree io.WriterTo) error { fp, err := os.OpenFile(cfgFile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) diff --git a/client/config/config_test.go b/client/config/config_test.go index 983bfbd97b90..0e0f64a166fd 100644 --- a/client/config/config_test.go +++ b/client/config/config_test.go @@ -50,6 +50,8 @@ func Test_runConfigCmdTwiceWithShorterNodeValue(t *testing.T) { err = cmd.RunE(cmd, []string{"invalidKey", "invalidValue"}) require.Equal(t, err, errUnknownConfigKey("invalidKey")) + // TODO add testing of pririty environmental variable, flag and file + } func tmpDir(t *testing.T) (string, func()) { diff --git a/client/config/toml.go b/client/config/toml.go new file mode 100644 index 000000000000..7332a81becac --- /dev/null +++ b/client/config/toml.go @@ -0,0 +1,87 @@ +package config + +import ( + "bytes" + "text/template" + "os" + "path" + + + "github.com/spf13/viper" + tmos "github.com/tendermint/tendermint/libs/os" +) + +const defaultConfigTemplate = `# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +############################################################################### +### Client Configuration ### +############################################################################### + + +chain-id = "{{ .ClientConfig.ChainID }}" +keyring-backend = "{{ .ClientConfig.KeyringBackend }}" +output = "{{ .ClientConfig.Output }}" +node = "{{ .ClientConfig.Node }}" +broadcast-mode = "{{ .ClientConfig.BroadcastMode }}" +trace = "{{ .ClientConfig.Trace }}" +` + +var configTemplate *template.Template + +func InitConfigTemplate() { + var err error + + tmpl := template.New("clientConfigFileTemplate") + + if configTemplate, err = tmpl.Parse(defaultConfigTemplate); err != nil { + panic(err) + } + +} + +// ParseConfig retrieves the default environment configuration for the +// application. +func ParseConfig() *ClientConfig { + conf := DefaultClientConfig() + _ = viper.Unmarshal(conf) + + return conf +} + +// WriteConfigFile renders config using the template and writes it to +// configFilePath. +func WriteConfigFile(configFilePath string, config *ClientConfig) { + var buffer bytes.Buffer + + if err := configTemplate.Execute(&buffer, config); err != nil { + panic(err) + } + + tmos.MustWriteFile(configFilePath, buffer.Bytes(), 0644) +} + +func ensureConfFile(rootDir string) (string, error) { + cfgPath := path.Join(rootDir, "config") + if err := os.MkdirAll(cfgPath, os.ModePerm); err != nil { // config directory + return "", err + } + + return cfgPath, nil +} + +func getClientConfig(cfgPath string) (*ClientConfig, error) { + viper.AddConfigPath(cfgPath) + viper.SetConfigName("client") + viper.SetConfigType("toml") + if err := viper.ReadInConfig(); err != nil { + return nil, err + } + + conf := new(ClientConfig) + if err := viper.Unmarshal(conf); err != nil { + return nil, err + } + + return conf,nil +} diff --git a/go.mod b/go.mod index 2a9836c0581e..3fc4d5184bf3 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/improbable-eng/grpc-web v0.14.0 github.com/magiconair/properties v1.8.4 github.com/mattn/go-isatty v0.0.12 + github.com/mitchellh/mapstructure v1.3.3 github.com/otiai10/copy v1.5.0 github.com/pelletier/go-toml v1.8.1 github.com/pkg/errors v0.9.1