diff --git a/client/cmd.go b/client/cmd.go index 84ca3926d7..78c5af7f32 100644 --- a/client/cmd.go +++ b/client/cmd.go @@ -63,6 +63,11 @@ func ValidateCmd(cmd *cobra.Command, args []string) error { // flags that do not necessarily change with context. These must be checked if // the caller explicitly changed the values. func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, error) { + if flagSet.Changed(flags.FlagHome) { + homeDir, _ := flagSet.GetString(flags.FlagHome) + clientCtx = clientCtx.WithHomeDir(homeDir) + } + if flagSet.Changed(flags.FlagChainID) { chainID, _ := flagSet.GetString(flags.FlagChainID) clientCtx = clientCtx.WithChainID(chainID) diff --git a/client/config.go b/client/config.go deleted file mode 100644 index 68ff9c6534..0000000000 --- a/client/config.go +++ /dev/null @@ -1,191 +0,0 @@ -package client - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "os" - "path" - "strconv" - "text/template" - - toml "github.com/pelletier/go-toml" - "github.com/spf13/cobra" - "github.com/spf13/viper" - - "github.com/cosmos/cosmos-sdk/client/flags" -) - -const ( - flagGet = "get" -) - -var configDefaults = map[string]string{ - "chain-id": "", - "keyring-backend": "os", - "output": "text", - "node": "tcp://localhost:26657", - "broadcast-mode": "sync", -} - -var configBoolDefaults = map[string]bool{ - "trace": false, - "trust-node": false, - "indent": false, - "offline": false, -} - -// ConfigCmd returns a CLI command to interactively create an application CLI -// config file. -func ConfigCmd(defaultCLIHome string) *cobra.Command { - cmd := &cobra.Command{ - Use: "config [value]", - Short: "Get and set client options", - Long: configCommandLongDescription(), - RunE: runConfigCmd, - Args: cobra.RangeArgs(0, 2), - } - - cmd.Flags().String(flags.FlagHome, defaultCLIHome, - "set client's home directory for configuration") - cmd.Flags().Bool(flagGet, false, - "print configuration value or its default if unset") - return cmd -} - -func runConfigCmd(cmd *cobra.Command, args []string) error { - cfgFile, err := ensureConfFile(viper.GetString(flags.FlagHome)) - if err != nil { - return err - } - - getAction := viper.GetBool(flagGet) - if getAction && len(args) != 1 { - return fmt.Errorf("wrong number of arguments") - } - - // load configuration - tree, err := loadConfigFile(cmd, cfgFile) - if err != nil { - return err - } - - // print the config and exit - if len(args) == 0 { - s, err := tree.ToTomlString() - if err != nil { - return err - } - cmd.Print(s) - return nil - } - - key := args[0] - - // get config value for a given key - if getAction { - if defaultValue, ok := configBoolDefaults[key]; ok { - cmd.Println(tree.GetDefault(key, defaultValue).(bool)) - return nil - } - - if defaultValue, ok := configDefaults[key]; ok { - cmd.Println(tree.GetDefault(key, defaultValue).(string)) - return nil - } - - return errUnknownConfigKey(key) - } - - if len(args) != 2 { - return fmt.Errorf("wrong number of arguments") - } - - value := args[1] - - // set config value for a given key - if _, ok := configBoolDefaults[key]; ok { - boolVal, err := strconv.ParseBool(value) - if err != nil { - return err - } - - tree.Set(key, boolVal) - } else if _, ok := configDefaults[key]; ok { - tree.Set(key, value) - } else { - return errUnknownConfigKey(key) - } - - // save configuration to disk - if err := saveConfigFile(cfgFile, tree); err != nil { - return err - } - - cmd.PrintErrf("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 { - return "", err - } - - return path.Join(cfgPath, "config.toml"), nil -} - -func loadConfigFile(cmd *cobra.Command, cfgFile string) (*toml.Tree, error) { - if _, err := os.Stat(cfgFile); os.IsNotExist(err) { - cmd.PrintErrf("%s does not exist\n", cfgFile) - return toml.Load(``) - } - - bz, err := ioutil.ReadFile(cfgFile) - if err != nil { - return nil, err - } - - tree, err := toml.LoadBytes(bz) - if err != nil { - return nil, err - } - - 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) - if err != nil { - return err - } - defer fp.Close() - - _, err = tree.WriteTo(fp) - return err -} - -func errUnknownConfigKey(key string) error { - return fmt.Errorf("unknown configuration key: %q", key) -} - -func configCommandLongDescription() string { - longDescTemplate := template.Must(template.New("configCommandLongDescription"). - Parse(`{{ range $key, $value := . }} {{ $key }} = {{ $value }} -{{ end }}`)) - defaultsTextBuffer := bytes.NewBufferString("") - must(longDescTemplate.Execute(defaultsTextBuffer, configDefaults)) - must(longDescTemplate.Execute(defaultsTextBuffer, configBoolDefaults)) - return fmt.Sprintf(`Display or change client application configuration values. - -Defaults: -%s`, defaultsTextBuffer) -} - -func must(err error) { - if err != nil { - panic(err) - } -} diff --git a/client/config_test.go b/client/config_test.go deleted file mode 100644 index 5a114a3e68..0000000000 --- a/client/config_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package client - -import ( - "os" - "path/filepath" - "testing" - - "github.com/spf13/viper" - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/tests" -) - -// For https://github.com/cosmos/cosmos-sdk/issues/3899 -func Test_runConfigCmdTwiceWithShorterNodeValue(t *testing.T) { - // Prepare environment - configHome, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - - _ = os.RemoveAll(filepath.Join(configHome, "config")) - viper.Set(flags.FlagHome, configHome) - - // Init command config - cmd := ConfigCmd(configHome) - require.NotNil(t, cmd) - require.NoError(t, cmd.RunE(cmd, []string{"node", "tcp://localhost:26657"})) - require.NoError(t, cmd.RunE(cmd, []string{"node", "--get"})) - require.NoError(t, cmd.RunE(cmd, []string{"node", "tcp://local:26657"})) - require.NoError(t, cmd.RunE(cmd, []string{"node", "--get"})) -} - -func TestConfigCmd_UnknownOption(t *testing.T) { - // Prepare environment - configHome, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - - _ = os.RemoveAll(filepath.Join(configHome, "config")) - viper.Set(flags.FlagHome, configHome) - - // Init command config - cmd := ConfigCmd(configHome) - require.NotNil(t, cmd) - require.Error(t, cmd.RunE(cmd, []string{"invalid", "true"}), "unknown configuration key: \"invalid\"") -} - -func TestConfigCmd_OfflineFlag(t *testing.T) { - // Prepare environment - configHome, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - - _ = os.RemoveAll(filepath.Join(configHome, "config")) - viper.Set(flags.FlagHome, configHome) - - // Init command config - cmd := ConfigCmd(configHome) - _, out, _ := tests.ApplyMockIO(cmd) - require.NotNil(t, cmd) - - viper.Set(flagGet, true) - require.NoError(t, cmd.RunE(cmd, []string{"offline"})) - require.Contains(t, out.String(), "false") - out.Reset() - - viper.Set(flagGet, false) - require.NoError(t, cmd.RunE(cmd, []string{"offline", "true"})) - - viper.Set(flagGet, true) - require.NoError(t, cmd.RunE(cmd, []string{"offline"})) - require.Contains(t, out.String(), "true") -} diff --git a/go.mod b/go.mod index 11e264f4eb..d0cb370c36 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/hashicorp/golang-lru v0.5.4 github.com/mattn/go-isatty v0.0.12 github.com/otiai10/copy v1.2.0 - github.com/pelletier/go-toml v1.8.0 + github.com/pelletier/go-toml v1.8.0 // indirect github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.7.1 github.com/prometheus/common v0.10.0 diff --git a/simapp/cmd/simcli/main.go b/simapp/cmd/simcli/main.go index cfcdbbc1c6..cef161ab42 100644 --- a/simapp/cmd/simcli/main.go +++ b/simapp/cmd/simcli/main.go @@ -3,12 +3,8 @@ package main import ( "fmt" "os" - "path" - - simappparams "github.com/cosmos/cosmos-sdk/simapp/params" "github.com/spf13/cobra" - "github.com/spf13/viper" "github.com/tendermint/tendermint/libs/cli" "github.com/cosmos/cosmos-sdk/client" @@ -25,6 +21,12 @@ import ( var ( encodingConfig = simapp.MakeEncodingConfig() + initClientCtx = client.Context{}. + WithJSONMarshaler(encodingConfig.Marshaler). + WithTxGenerator(encodingConfig.TxGenerator). + WithCodec(encodingConfig.Amino). + WithInput(os.Stdin). + WithAccountRetriever(types.NewAccountRetriever(encodingConfig.Marshaler)) ) func init() { @@ -48,21 +50,17 @@ func main() { rootCmd := &cobra.Command{ Use: "simcli", - Short: "Command line interface for interacting with simd", + Short: "Command line interface for interacting with simapp", } // Add --chain-id to persistent flags and mark it required - rootCmd.PersistentFlags().String(flags.FlagChainID, "", "Chain ID of tendermint node") - rootCmd.PersistentPreRunE = func(_ *cobra.Command, _ []string) error { - return initConfig(rootCmd) - } + rootCmd.PersistentFlags().String(flags.FlagChainID, "", "network chain ID") // Construct Root Command rootCmd.AddCommand( rpc.StatusCommand(), - client.ConfigCmd(simapp.DefaultCLIHome), - queryCmd(encodingConfig), - txCmd(encodingConfig), + queryCmd(), + txCmd(), flags.LineBreak, flags.LineBreak, keys.Commands(), @@ -80,7 +78,7 @@ func main() { } } -func queryCmd(config simappparams.EncodingConfig) *cobra.Command { +func queryCmd() *cobra.Command { queryCmd := &cobra.Command{ Use: "query", Aliases: []string{"q"}, @@ -90,30 +88,22 @@ func queryCmd(config simappparams.EncodingConfig) *cobra.Command { RunE: client.ValidateCmd, } - cdc := config.Amino - queryCmd.AddCommand( - authcmd.GetAccountCmd(cdc), + authcmd.GetAccountCmd(encodingConfig.Amino), flags.LineBreak, - rpc.ValidatorCommand(cdc), + rpc.ValidatorCommand(encodingConfig.Amino), rpc.BlockCommand(), - authcmd.QueryTxsByEventsCmd(cdc), - authcmd.QueryTxCmd(cdc), + authcmd.QueryTxsByEventsCmd(encodingConfig.Amino), + authcmd.QueryTxCmd(encodingConfig.Amino), flags.LineBreak, ) - // add modules' query commands - clientCtx := client.Context{} - clientCtx = clientCtx. - WithJSONMarshaler(config.Marshaler). - WithCodec(cdc) - - simapp.ModuleBasics.AddQueryCommands(queryCmd, clientCtx) + simapp.ModuleBasics.AddQueryCommands(queryCmd, initClientCtx) return queryCmd } -func txCmd(config simappparams.EncodingConfig) *cobra.Command { +func txCmd() *cobra.Command { txCmd := &cobra.Command{ Use: "tx", Short: "Transactions subcommands", @@ -122,53 +112,21 @@ func txCmd(config simappparams.EncodingConfig) *cobra.Command { RunE: client.ValidateCmd, } - cdc := config.Amino - clientCtx := client.Context{} - clientCtx = clientCtx. - WithJSONMarshaler(config.Marshaler). - WithTxGenerator(config.TxGenerator). - WithAccountRetriever(types.NewAccountRetriever(config.Marshaler)). - WithCodec(cdc) - txCmd.AddCommand( - bankcmd.NewSendTxCmd(clientCtx), + bankcmd.NewSendTxCmd(initClientCtx), flags.LineBreak, - authcmd.GetSignCommand(clientCtx), - authcmd.GetSignBatchCommand(cdc), - authcmd.GetMultiSignCommand(clientCtx), - authcmd.GetValidateSignaturesCommand(clientCtx), + authcmd.GetSignCommand(initClientCtx), + authcmd.GetSignBatchCommand(encodingConfig.Amino), + authcmd.GetMultiSignCommand(initClientCtx), + authcmd.GetValidateSignaturesCommand(initClientCtx), flags.LineBreak, - authcmd.GetBroadcastCommand(clientCtx), - authcmd.GetEncodeCommand(clientCtx), - authcmd.GetDecodeCommand(clientCtx), + authcmd.GetBroadcastCommand(initClientCtx), + authcmd.GetEncodeCommand(initClientCtx), + authcmd.GetDecodeCommand(initClientCtx), flags.LineBreak, ) - // add modules' tx commands - simapp.ModuleBasics.AddTxCommands(txCmd, clientCtx) + simapp.ModuleBasics.AddTxCommands(txCmd, initClientCtx) return txCmd } - -func initConfig(cmd *cobra.Command) error { - home, err := cmd.PersistentFlags().GetString(cli.HomeFlag) - if err != nil { - return err - } - - cfgFile := path.Join(home, "config", "config.toml") - if _, err := os.Stat(cfgFile); err == nil { - viper.SetConfigFile(cfgFile) - - if err := viper.ReadInConfig(); err != nil { - return err - } - } - if err := viper.BindPFlag(flags.FlagChainID, cmd.PersistentFlags().Lookup(flags.FlagChainID)); err != nil { - return err - } - if err := viper.BindPFlag(cli.EncodingFlag, cmd.PersistentFlags().Lookup(cli.EncodingFlag)); err != nil { - return err - } - return viper.BindPFlag(cli.OutputFlag, cmd.PersistentFlags().Lookup(cli.OutputFlag)) -} diff --git a/tests/cli/helpers.go b/tests/cli/helpers.go index 72e665b0b8..1abade3bae 100644 --- a/tests/cli/helpers.go +++ b/tests/cli/helpers.go @@ -141,8 +141,7 @@ func (f *Fixtures) KeysAddRecoverHDPath(name, mnemonic string, account uint32, i // KeysShow is simcli keys show func (f *Fixtures) KeysShow(name string, flags ...string) keyring.KeyOutput { - cmd := fmt.Sprintf("%s keys show --keyring-backend=test --home=%s %s", f.SimcliBinary, - f.SimcliHome, name) + cmd := fmt.Sprintf("%s keys show --keyring-backend=test --home=%s %s --output=json", f.SimcliBinary, f.SimcliHome, name) out, _ := tests.ExecuteT(f.T, AddFlags(cmd, flags), "") var ko keyring.KeyOutput err := clientkeys.UnmarshalJSON([]byte(out), &ko) @@ -173,15 +172,6 @@ func (f *Fixtures) QueryTxs(page, limit int, events ...string) *sdk.SearchTxsRes return &result } -//___________________________________________________________________________________ -// simcli config - -// CLIConfig is simcli config -func (f *Fixtures) CLIConfig(key, value string, flags ...string) { - cmd := fmt.Sprintf("%s config --home=%s %s %s", f.SimcliBinary, f.SimcliHome, key, value) - ExecuteWriteCheckErr(f.T, AddFlags(cmd, flags)) -} - //utils func AddFlags(cmd string, flags []string) string { diff --git a/tests/cli/init.go b/tests/cli/init.go index 3a6efa98cc..418122975c 100644 --- a/tests/cli/init.go +++ b/tests/cli/init.go @@ -17,8 +17,6 @@ func InitFixtures(t *testing.T) (f *Fixtures) { // reset test state f.UnsafeResetAll() - f.CLIConfig("keyring-backend", "test") - // ensure keystore has foo and bar keys f.KeysDelete(KeyFoo) f.KeysDelete(KeyBar) @@ -28,19 +26,11 @@ func InitFixtures(t *testing.T) (f *Fixtures) { f.KeysAdd(KeyBar) f.KeysAdd(KeyBaz) f.KeysAdd(KeyVesting) - f.KeysAdd(KeyFooBarBaz, "--multisig-threshold=2", fmt.Sprintf( - "--multisig=%s,%s,%s", KeyFoo, KeyBar, KeyBaz)) - - // ensure that CLI output is in JSON format - f.CLIConfig("output", "json") + f.KeysAdd(KeyFooBarBaz, "--multisig-threshold=2", fmt.Sprintf("--multisig=%s,%s,%s", KeyFoo, KeyBar, KeyBaz)) // NOTE: SDInit sets the ChainID f.SDInit(KeyFoo) - f.CLIConfig("chain-id", f.ChainID) - f.CLIConfig("broadcast-mode", "block") - f.CLIConfig("trust-node", "true") - // start an account with tokens f.AddGenesisAccount(f.KeyAddress(KeyFoo), StartCoins) f.AddGenesisAccount( @@ -66,5 +56,5 @@ func (f *Fixtures) Cleanup(dirs ...string) { // Flags returns the flags necessary for making most CLI calls func (f *Fixtures) Flags() string { - return fmt.Sprintf("--home=%s --node=%s", f.SimcliHome, f.RPCAddr) + return fmt.Sprintf("--home=%s --node=%s --chain-id=%s --output=json", f.SimcliHome, f.RPCAddr, f.ChainID) } diff --git a/tests/cli/simd_test.go b/tests/cli/simd_test.go index 329127925b..391139e54c 100644 --- a/tests/cli/simd_test.go +++ b/tests/cli/simd_test.go @@ -33,9 +33,6 @@ func TestCLISimdCollectGentxs(t *testing.T) { // Initialize keys f.KeysAdd(cli.KeyFoo) - // Configure json output - f.CLIConfig("output", "json") - // Run init f.SDInit(cli.KeyFoo) @@ -80,9 +77,6 @@ func TestCLISimdAddGenesisAccount(t *testing.T) { f.KeysAdd(cli.KeyBar) f.KeysAdd(cli.KeyBaz) - // Configure json output - f.CLIConfig("output", "json") - // Run init f.SDInit(cli.KeyFoo) diff --git a/x/distribution/client/cli/cli_test.go b/x/distribution/client/cli/cli_test.go index af760148c5..524829739b 100644 --- a/x/distribution/client/cli/cli_test.go +++ b/x/distribution/client/cli/cli_test.go @@ -66,7 +66,7 @@ func TestCLIWithdrawRewards(t *testing.T) { rewards = testutil.QueryRewards(f, fooAddr) require.Len(t, rewards.Rewards, 1) - require.Nil(t, rewards.Total) + require.Len(t, rewards.Total, 1) // Setting up a new withdraw address success, stdout, stderr := testutil.TxSetWithdrawAddress(f, fooAddr.String(), barAddr.String(), "--generate-only") diff --git a/x/staking/client/cli/cli_test.go b/x/staking/client/cli/cli_test.go index 0032f49837..4a1c455cd6 100644 --- a/x/staking/client/cli/cli_test.go +++ b/x/staking/client/cli/cli_test.go @@ -40,7 +40,7 @@ func TestCLICreateValidator(t *testing.T) { bankclienttestutil.TxSend(f, cli.KeyFoo, barAddr, sdk.NewCoin(cli.Denom, sendTokens), "-y") tests.WaitForNextNBlocksTM(1, f.Port) - require.Equal(t, sendTokens, bankclienttestutil.QueryBalances(f, barAddr).AmountOf(cli.Denom)) + require.Equal(t, sendTokens.String(), bankclienttestutil.QueryBalances(f, barAddr).AmountOf(cli.Denom).String()) // Generate a create validator transaction and ensure correctness success, stdout, stderr := testutil.TxStakingCreateValidator(f, barAddr.String(), consPubKey, sdk.NewInt64Coin(cli.Denom, 2), "--generate-only")