-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
R4R: Fix gaiacli config and make it non-interactive only #2972
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
7b94da2
Fix gaiacli config and make it non-interactive only
43025ce
Update cli tests
6de02de
Remove --list, by default and with no args print config
82eab7b
Small improvements
db5369b
Warn user when file doesn't exist
1f188b4
Fix integration tests
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,131 +1,157 @@ | ||
package client | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"path" | ||
"strconv" | ||
|
||
"github.com/cosmos/cosmos-sdk/cmd/gaia/app" | ||
"github.com/tendermint/tendermint/libs/cli" | ||
|
||
"github.com/cosmos/cosmos-sdk/types" | ||
"github.com/mitchellh/go-homedir" | ||
"github.com/pelletier/go-toml" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
const ( | ||
flagGet = "get" | ||
) | ||
|
||
type cliConfig struct { | ||
Home string `toml:"home"` | ||
ChainID string `toml:"chain_id"` | ||
TrustNode bool `toml:"trust_node"` | ||
Output string `toml:"output"` | ||
Node string `toml:"node"` | ||
Trace bool `toml:"trace"` | ||
var configDefaults map[string]string | ||
|
||
func init() { | ||
configDefaults = map[string]string{ | ||
"chain_id": "", | ||
"output": "text", | ||
"node": "tcp://localhost:26657", | ||
} | ||
} | ||
|
||
// 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", | ||
cmd := &cobra.Command{ | ||
Use: "config <key> [value]", | ||
Short: "Create or query a Gaia CLI configuration file", | ||
RunE: runConfigCmd, | ||
Args: cobra.RangeArgs(0, 2), | ||
} | ||
|
||
return cfg | ||
cmd.Flags().String(cli.HomeFlag, app.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 { | ||
home, err := homedir.Dir() | ||
cfgFile, err := ensureConfFile(viper.GetString(cli.HomeFlag)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
stdin := BufferStdin() | ||
|
||
gaiaCLIHome, err := handleGaiaCLIHome(home, stdin) | ||
if err != nil { | ||
return err | ||
getAction := viper.GetBool(flagGet) | ||
if getAction && len(args) != 1 { | ||
return fmt.Errorf("wrong number of arguments") | ||
} | ||
|
||
node, err := handleNode(stdin) | ||
// Load configuration | ||
tree, err := loadConfigFile(cfgFile) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
trustNode, err := handleTrustNode(stdin) | ||
if err != nil { | ||
return err | ||
// Print the config and exit | ||
if len(args) == 0 { | ||
s, err := tree.ToTomlString() | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Print(s) | ||
return nil | ||
} | ||
|
||
chainID, err := types.DefaultChainID() | ||
key := args[0] | ||
// Get value action | ||
if getAction { | ||
switch key { | ||
case "trace", "trust_node": | ||
fmt.Println(tree.GetDefault(key, false).(bool)) | ||
default: | ||
if defaultValue, ok := configDefaults[key]; ok { | ||
fmt.Println(tree.GetDefault(key, defaultValue).(string)) | ||
return nil | ||
} | ||
return errUnknownConfigKey(key) | ||
} | ||
return nil | ||
} | ||
|
||
if err != nil { | ||
fmt.Println("Couldn't populate ChainID, so using an empty one.") | ||
// Set value action | ||
value := args[1] | ||
switch key { | ||
case "chain_id", "output", "node": | ||
cwgoes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
tree.Set(key, value) | ||
case "trace", "trust_node": | ||
boolVal, err := strconv.ParseBool(value) | ||
if err != nil { | ||
return err | ||
} | ||
tree.Set(key, boolVal) | ||
default: | ||
return errUnknownConfigKey(key) | ||
} | ||
|
||
cfg := &cliConfig{ | ||
Home: gaiaCLIHome, | ||
ChainID: chainID, | ||
TrustNode: trustNode, | ||
Output: "text", | ||
Node: node, | ||
Trace: false, | ||
// Save configuration to disk | ||
if err := saveConfigFile(cfgFile, tree); err != nil { | ||
return err | ||
} | ||
fmt.Fprintf(os.Stderr, "configuration saved to %s\n", cfgFile) | ||
|
||
return createGaiaCLIConfig(cfg) | ||
return nil | ||
} | ||
|
||
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 { | ||
func ensureConfFile(rootDir string) (string, error) { | ||
cfgPath := path.Join(rootDir, "config") | ||
if err := os.MkdirAll(cfgPath, os.ModePerm); err != nil { | ||
return "", err | ||
} | ||
|
||
if home == "" { | ||
home = path.Join(dir, dirName) | ||
} | ||
|
||
return home, nil | ||
return path.Join(cfgPath, "config.toml"), 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 | ||
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) | ||
return toml.Load(``) | ||
} | ||
|
||
if node == "" { | ||
node = defaultNode | ||
bz, err := ioutil.ReadFile(cfgFile) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
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) | ||
tree, err := toml.LoadBytes(bz) | ||
if err != nil { | ||
return err | ||
return nil, err | ||
} | ||
|
||
data, err := toml.Marshal(*cfg) | ||
return tree, nil | ||
} | ||
|
||
func saveConfigFile(cfgFile string, tree *toml.Tree) error { | ||
fp, err := os.OpenFile(cfgFile, os.O_WRONLY|os.O_CREATE, 0644) | ||
if err != nil { | ||
return err | ||
} | ||
defer fp.Close() | ||
|
||
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 | ||
} | ||
} | ||
_, err = tree.WriteTo(fp) | ||
return err | ||
} | ||
|
||
return ioutil.WriteFile(cfgFile, data, os.ModePerm) | ||
func errUnknownConfigKey(key string) error { | ||
return fmt.Errorf("unknown configuration key: %q", key) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CLI flag and this should just use a constant variable, no? Just to be safe.