Skip to content

Commit

Permalink
Merge PR cosmos#2223: Gaia CLI Config Command
Browse files Browse the repository at this point in the history
* Allow a gaia-cli config file to be created

Closes cosmos#1613.
Closes cosmos#1275.
Closes cosmos#1956.

* Add homedir to Gopkg.toml

* Updates from code review

* Post-rebase fixes

* Update test

* Code review refactor

* Fixes from code review

* Fix import

* Fix broken test

* Fixes from rebase

* Fix formatting
  • Loading branch information
mslipper authored and rigelrozanski committed Sep 25, 2018
1 parent 24413a3 commit 2fb3493
Show file tree
Hide file tree
Showing 18 changed files with 298 additions and 31 deletions.
10 changes: 10 additions & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,7 @@
[prune]
go-tests = true
unused-packages = true

[[constraint]]
name = "github.com/mitchellh/go-homedir"
version = "1.0.0"
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ FEATURES
* [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add --generate-only flag to build an unsigned transaction and write it to STDOUT.
* [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) New `sign` command to sign transactions generated with the --generate-only flag.
* [\#1954](https://github.com/cosmos/cosmos-sdk/issues/1954) New `broadcast` command to broadcast transactions generated offline and signed with the `sign` command.
* [cli] \#2220 Add `gaiacli config` feature to interactively create CLI config files to reduce the number of required flags
* [stake][cli] [\#1672](https://github.com/cosmos/cosmos-sdk/issues/1672) Introduced
new commission flags for validator commands `create-validator` and `edit-validator`.

Expand Down
131 changes: 131 additions & 0 deletions client/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package client

import (
"github.com/spf13/cobra"
"github.com/mitchellh/go-homedir"
"bufio"
"path"
"os"
"io/ioutil"
"github.com/pelletier/go-toml"
"fmt"
"github.com/cosmos/cosmos-sdk/types"
)

type cliConfig struct {
Home string `toml:"home"`
ChainID string `toml:"chain_id"`
TrustNode bool `toml:"trust_node"`
Encoding string `toml:"encoding"`
Output string `toml:"output"`
Node string `toml:"node"`
Trace bool `toml:"trace"`
}

// ConfigCmd returns a CLI command to interactively create a
// Gaia CLI config file.
func ConfigCmd() *cobra.Command {
cfg := &cobra.Command{
Use: "config",
Short: "Interactively creates a Gaia CLI config file",
RunE: runConfigCmd,
}

return cfg
}

func runConfigCmd(cmd *cobra.Command, args [] string) error {
home, err := homedir.Dir()
if err != nil {
return err
}

stdin := BufferStdin()
gaiaCLIHome, err := handleGaiaCLIHome(home, stdin)
if err != nil {
return err
}
node, err := handleNode(stdin)
if err != nil {
return err
}
trustNode, err := handleTrustNode(stdin)
if err != nil {
return err
}

encoding := "btc"
output := "text"
var chainID string
chainID, err = types.DefaultChainID()
if err != nil {
fmt.Println("Couldn't populate ChainID, so using an empty one.")
}

cfg := &cliConfig{
Home: gaiaCLIHome,
ChainID: chainID,
TrustNode: trustNode,
Encoding: encoding,
Output: output,
Node: node,
Trace: false,
}

return createGaiaCLIConfig(cfg)
}

func handleGaiaCLIHome(dir string, stdin *bufio.Reader) (string, error) {
dirName := ".gaiacli"
home, err := GetString(fmt.Sprintf("Where is your gaiacli home directory? (Default: ~/%s)", dirName), stdin)
if err != nil {
return "", err
}

if home == "" {
home = path.Join(dir, dirName)
}

return home, nil
}

func handleNode(stdin *bufio.Reader) (string, error) {
defaultNode := "tcp://localhost:26657"
node, err := GetString(fmt.Sprintf("Where is your validator node running? (Default: %s)", defaultNode), stdin)
if err != nil {
return "", err
}

if node == "" {
node = defaultNode
}

return node, nil
}

func handleTrustNode(stdin *bufio.Reader) (bool, error) {
return GetConfirmation("Do you trust this node?", stdin)
}

func createGaiaCLIConfig(cfg *cliConfig) error {
cfgPath := path.Join(cfg.Home, "config")
err := os.MkdirAll(cfgPath, os.ModePerm)
if err != nil {
return err
}

data, err := toml.Marshal(*cfg)
if err != nil {
return err
}

cfgFile := path.Join(cfgPath, "config.toml")
if info, err := os.Stat(cfgFile); err == nil && !info.IsDir() {
err = os.Rename(cfgFile, path.Join(cfgPath, "config.toml-old"))
if err != nil {
return err
}
}

return ioutil.WriteFile(cfgFile, data, os.ModePerm)
}
9 changes: 9 additions & 0 deletions client/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strconv"

"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// nolint
Expand Down Expand Up @@ -51,6 +52,10 @@ func GetCommands(cmds ...*cobra.Command) []*cobra.Command {
c.Flags().String(FlagChainID, "", "Chain ID of tendermint node")
c.Flags().String(FlagNode, "tcp://localhost:26657", "<host>:<port> to tendermint rpc interface for this chain")
c.Flags().Int64(FlagHeight, 0, "block height to query, omit to get most recent provable block")
viper.BindPFlag(FlagTrustNode, c.Flags().Lookup(FlagTrustNode))
viper.BindPFlag(FlagUseLedger, c.Flags().Lookup(FlagUseLedger))
viper.BindPFlag(FlagChainID, c.Flags().Lookup(FlagChainID))
viper.BindPFlag(FlagNode, c.Flags().Lookup(FlagNode))
}
return cmds
}
Expand All @@ -76,6 +81,10 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
// --gas can accept integers and "simulate"
c.Flags().Var(&GasFlagVar, "gas", fmt.Sprintf(
"gas limit to set per-transaction; set to %q to calculate required gas automatically (default %d)", GasFlagSimulate, DefaultGasLimit))
viper.BindPFlag(FlagTrustNode, c.Flags().Lookup(FlagTrustNode))
viper.BindPFlag(FlagUseLedger, c.Flags().Lookup(FlagUseLedger))
viper.BindPFlag(FlagChainID, c.Flags().Lookup(FlagChainID))
viper.BindPFlag(FlagNode, c.Flags().Lookup(FlagNode))
}
return cmds
}
Expand Down
18 changes: 18 additions & 0 deletions client/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ func GetConfirmation(prompt string, buf *bufio.Reader) (bool, error) {
}
}

// GetString simply returns the trimmed string output of a given reader.
func GetString(prompt string, buf *bufio.Reader) (string, error) {
if inputIsTty() && prompt != "" {
PrintPrefixed(prompt)
}

out, err := readLineFromBuf(buf)
if err != nil {
return "", err
}
return strings.TrimSpace(out), nil
}

// inputIsTty returns true iff we have an interactive prompt,
// where we can disable echo and request to repeat the password.
// If false, we can optimize for piped input from another command
Expand All @@ -117,3 +130,8 @@ func readLineFromBuf(buf *bufio.Reader) (string, error) {
}
return strings.TrimSpace(pass), nil
}

// PrintPrefixed prints a string with > prefixed for use in prompts.
func PrintPrefixed(msg string) {
fmt.Printf("> %s\n", msg)
}
3 changes: 3 additions & 0 deletions client/lcd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ func ServeCommand(cdc *codec.Codec) *cobra.Command {
cmd.Flags().String(client.FlagNode, "tcp://localhost:26657", "Address of the node to connect to")
cmd.Flags().Int(flagMaxOpenConnections, 1000, "The number of maximum open connections")
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
viper.BindPFlag(client.FlagTrustNode, cmd.Flags().Lookup(client.FlagTrustNode))
viper.BindPFlag(client.FlagChainID, cmd.Flags().Lookup(client.FlagChainID))
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))

return cmd
}
Expand Down
3 changes: 3 additions & 0 deletions client/rpc/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/gorilla/mux"
"github.com/spf13/cobra"
"github.com/spf13/viper"
tmliteProxy "github.com/tendermint/tendermint/lite/proxy"
)

Expand All @@ -22,7 +23,9 @@ func BlockCommand() *cobra.Command {
RunE: printBlock,
}
cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
viper.BindPFlag(client.FlagTrustNode, cmd.Flags().Lookup(client.FlagTrustNode))
cmd.Flags().String(client.FlagChainID, "", "Chain ID of Tendermint node")
return cmd
}
Expand Down
4 changes: 4 additions & 0 deletions client/rpc/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/spf13/viper"
)

const (
Expand Down Expand Up @@ -40,6 +41,9 @@ func initClientCommand() *cobra.Command {
cmd.Flags().String(flagGenesis, "", "Genesis file to verify header validity")
cmd.Flags().String(flagCommit, "", "File with trusted and signed header")
cmd.Flags().String(flagValHash, "", "Hash of trusted validator set (hex-encoded)")
viper.BindPFlag(client.FlagChainID, cmd.Flags().Lookup(client.FlagChainID))
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))

return cmd
}

Expand Down
2 changes: 2 additions & 0 deletions client/rpc/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
"github.com/spf13/viper"
)

func statusCommand() *cobra.Command {
Expand All @@ -20,6 +21,7 @@ func statusCommand() *cobra.Command {
}

cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))
return cmd
}

Expand Down
4 changes: 4 additions & 0 deletions client/rpc/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/spf13/viper"
)

// TODO these next two functions feel kinda hacky based on their placement
Expand All @@ -26,8 +27,11 @@ func ValidatorCommand() *cobra.Command {
RunE: printValidators,
}
cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
viper.BindPFlag(client.FlagTrustNode, cmd.Flags().Lookup(client.FlagTrustNode))
cmd.Flags().String(client.FlagChainID, "", "Chain ID of Tendermint node")
viper.BindPFlag(client.FlagChainID, cmd.Flags().Lookup(client.FlagChainID))
return cmd
}

Expand Down
8 changes: 6 additions & 2 deletions client/tx/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package tx
import (
"encoding/hex"
"fmt"
"github.com/tendermint/tendermint/libs/common"
"net/http"
"github.com/tendermint/tendermint/libs/common"

"github.com/gorilla/mux"
"github.com/spf13/cobra"
Expand All @@ -16,6 +16,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/spf13/viper"
)

// QueryTxCmd implements the default command for a tx query.
Expand All @@ -41,8 +42,11 @@ func QueryTxCmd(cdc *codec.Codec) *cobra.Command {
}

cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))
cmd.Flags().String(client.FlagChainID, "", "Chain ID of Tendermint node")
viper.BindPFlag(client.FlagChainID, cmd.Flags().Lookup(client.FlagChainID))
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
viper.BindPFlag(client.FlagTrustNode, cmd.Flags().Lookup(client.FlagTrustNode))
return cmd
}

Expand Down
5 changes: 4 additions & 1 deletion client/tx/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ $ gaiacli tendermint txs --tag test1,test2 --any
}

cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))
cmd.Flags().String(client.FlagChainID, "", "Chain ID of Tendermint node")
viper.BindPFlag(client.FlagChainID, cmd.Flags().Lookup(client.FlagChainID))
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
viper.BindPFlag(client.FlagTrustNode, cmd.Flags().Lookup(client.FlagTrustNode))
cmd.Flags().StringSlice(flagTags, nil, "Comma-separated list of tags that must match")
cmd.Flags().Bool(flagAny, false, "Return transactions that match ANY tag, rather than ALL")
return cmd
Expand Down
Loading

0 comments on commit 2fb3493

Please sign in to comment.