-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Add client config subcommand to CLI #8953
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
6135d37
add client config
cyberbono3 1258d25
addressed reviewers comments
cyberbono3 fe12325
refactored,ready for review
cyberbono3 fc5b76a
fixed linter issues and addressed reviewers comments
cyberbono3 4d09403
Bump golangci-lint
32b2d15
fix linter warnings
d6f55a4
fix some tests
cyberbono3 4b79ade
Merge branch 'master' into cyberbono3/8529-add-client-config
amaury1093 4a5a2b2
Merge branch 'master' into cyberbono3/8529-add-client-config
amaury1093 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
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 |
---|---|---|
|
@@ -8,7 +8,6 @@ import ( | |
"github.com/spf13/cobra" | ||
"github.com/spf13/pflag" | ||
"github.com/tendermint/tendermint/libs/cli" | ||
rpchttp "github.com/tendermint/tendermint/rpc/client/http" | ||
|
||
"github.com/cosmos/cosmos-sdk/client/flags" | ||
"github.com/cosmos/cosmos-sdk/crypto/keyring" | ||
|
@@ -94,11 +93,6 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont | |
clientCtx = clientCtx.WithOutputFormat(output) | ||
} | ||
|
||
if clientCtx.HomeDir == "" || flagSet.Changed(flags.FlagHome) { | ||
homeDir, _ := flagSet.GetString(flags.FlagHome) | ||
clientCtx = clientCtx.WithHomeDir(homeDir) | ||
} | ||
|
||
if !clientCtx.Simulate || flagSet.Changed(flags.FlagDryRun) { | ||
dryRun, _ := flagSet.GetBool(flags.FlagDryRun) | ||
clientCtx = clientCtx.WithSimulation(dryRun) | ||
|
@@ -125,7 +119,7 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont | |
keyringBackend, _ := flagSet.GetString(flags.FlagKeyringBackend) | ||
|
||
if keyringBackend != "" { | ||
kr, err := newKeyringFromFlags(clientCtx, keyringBackend) | ||
kr, err := NewKeyringFromBackend(clientCtx, keyringBackend) | ||
if err != nil { | ||
return clientCtx, err | ||
} | ||
|
@@ -139,7 +133,7 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont | |
if rpcURI != "" { | ||
clientCtx = clientCtx.WithNodeURI(rpcURI) | ||
|
||
client, err := rpchttp.New(rpcURI, "/websocket") | ||
client, err := NewClientFromNode(rpcURI) | ||
if err != nil { | ||
return clientCtx, err | ||
} | ||
|
@@ -255,6 +249,21 @@ func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, err | |
return clientCtx, nil | ||
} | ||
|
||
// ReadHomeFlag checks if home flag is changed. | ||
// If this is a case, we update HomeDir field of Client Context | ||
/* Discovered a bug with Cory | ||
./build/simd init andrei --home ./test | ||
cd test/config there is no client.toml configuration file | ||
*/ | ||
func ReadHomeFlag(clientCtx Context, cmd *cobra.Command) Context { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can L96-L99 call this function too? |
||
if cmd.Flags().Changed(flags.FlagHome) { | ||
rootDir, _ := cmd.Flags().GetString(flags.FlagHome) | ||
clientCtx = clientCtx.WithHomeDir(rootDir) | ||
} | ||
|
||
return clientCtx | ||
} | ||
|
||
// GetClientQueryContext returns a Context from a command with fields set based on flags | ||
// defined in AddQueryFlagsToCmd. An error is returned if any flag query fails. | ||
// | ||
|
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 |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package config | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"path/filepath" | ||
|
||
tmcli "github.com/tendermint/tendermint/libs/cli" | ||
|
||
"github.com/spf13/cobra" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/cosmos-sdk/client/flags" | ||
) | ||
|
||
// Cmd returns a CLI command to interactively create an application CLI | ||
// config file. | ||
func Cmd() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "config <key> [value]", | ||
Short: "Create or query an application CLI configuration file", | ||
RunE: runConfigCmd, | ||
Args: cobra.RangeArgs(0, 2), | ||
} | ||
return cmd | ||
} | ||
|
||
func runConfigCmd(cmd *cobra.Command, args []string) error { | ||
clientCtx := client.GetClientContextFromCmd(cmd) | ||
configPath := filepath.Join(clientCtx.HomeDir, "config") | ||
|
||
conf, err := getClientConfig(configPath, clientCtx.Viper) | ||
if err != nil { | ||
return fmt.Errorf("couldn't get client config: %v", err) | ||
} | ||
|
||
switch len(args) { | ||
case 0: | ||
// print all client config fields to sdt out | ||
s, _ := json.MarshalIndent(conf, "", "\t") | ||
cmd.Println(string(s)) | ||
|
||
case 1: | ||
// it's a get | ||
key := args[0] | ||
|
||
switch key { | ||
case flags.FlagChainID: | ||
cmd.Println(conf.ChainID) | ||
case flags.FlagKeyringBackend: | ||
cmd.Println(conf.KeyringBackend) | ||
case tmcli.OutputFlag: | ||
cmd.Println(conf.Output) | ||
case flags.FlagNode: | ||
cmd.Println(conf.Node) | ||
case flags.FlagBroadcastMode: | ||
cmd.Println(conf.BroadcastMode) | ||
default: | ||
err := errUnknownConfigKey(key) | ||
return fmt.Errorf("couldn't get the value for the key: %v, error: %v", key, err) | ||
} | ||
|
||
case 2: | ||
// it's set | ||
key, value := args[0], args[1] | ||
|
||
switch key { | ||
case flags.FlagChainID: | ||
conf.SetChainID(value) | ||
case flags.FlagKeyringBackend: | ||
conf.SetKeyringBackend(value) | ||
case tmcli.OutputFlag: | ||
conf.SetOutput(value) | ||
case flags.FlagNode: | ||
conf.SetNode(value) | ||
case flags.FlagBroadcastMode: | ||
conf.SetBroadcastMode(value) | ||
default: | ||
return errUnknownConfigKey(key) | ||
} | ||
|
||
confFile := filepath.Join(configPath, "client.toml") | ||
if err := writeConfigToFile(confFile, conf); err != nil { | ||
return fmt.Errorf("could not write client config to the file: %v", err) | ||
} | ||
|
||
default: | ||
panic("cound not execute config command") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func errUnknownConfigKey(key string) error { | ||
return fmt.Errorf("unknown configuration key: %q", key) | ||
} |
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 |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package config | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
) | ||
|
||
// Default constants | ||
const ( | ||
chainID = "" | ||
keyringBackend = "os" | ||
output = "text" | ||
node = "tcp://localhost:26657" | ||
broadcastMode = "sync" | ||
) | ||
|
||
type ClientConfig struct { | ||
ChainID string `mapstructure:"chain-id" json:"chain-id"` | ||
KeyringBackend string `mapstructure:"keyring-backend" json:"keyring-backend"` | ||
Output string `mapstructure:"output" json:"output"` | ||
Node string `mapstructure:"node" json:"node"` | ||
BroadcastMode string `mapstructure:"broadcast-mode" json:"broadcast-mode"` | ||
} | ||
|
||
// defaultClientConfig returns the reference to ClientConfig with default values. | ||
func defaultClientConfig() *ClientConfig { | ||
return &ClientConfig{chainID, keyringBackend, output, node, broadcastMode} | ||
} | ||
|
||
func (c *ClientConfig) SetChainID(chainID string) { | ||
c.ChainID = chainID | ||
} | ||
|
||
func (c *ClientConfig) SetKeyringBackend(keyringBackend string) { | ||
c.KeyringBackend = keyringBackend | ||
} | ||
|
||
func (c *ClientConfig) SetOutput(output string) { | ||
c.Output = output | ||
} | ||
|
||
func (c *ClientConfig) SetNode(node string) { | ||
c.Node = node | ||
} | ||
|
||
func (c *ClientConfig) SetBroadcastMode(broadcastMode string) { | ||
c.BroadcastMode = broadcastMode | ||
} | ||
|
||
// ReadFromClientConfig reads values from client.toml file and updates them in client Context | ||
func ReadFromClientConfig(ctx client.Context) (client.Context, error) { | ||
configPath := filepath.Join(ctx.HomeDir, "config") | ||
configFilePath := filepath.Join(configPath, "client.toml") | ||
conf := defaultClientConfig() | ||
|
||
// if config.toml file does not exist we create it and write default ClientConfig values into it. | ||
if _, err := os.Stat(configFilePath); os.IsNotExist(err) { | ||
if err := ensureConfigPath(configPath); err != nil { | ||
return ctx, fmt.Errorf("couldn't make client config: %v", err) | ||
} | ||
|
||
if err := writeConfigToFile(configFilePath, conf); err != nil { | ||
return ctx, fmt.Errorf("could not write client config to the file: %v", err) | ||
} | ||
} | ||
|
||
conf, err := getClientConfig(configPath, ctx.Viper) | ||
if err != nil { | ||
return ctx, fmt.Errorf("couldn't get client config: %v", err) | ||
} | ||
// we need to update KeyringDir field on Client Context first cause it is used in NewKeyringFromBackend | ||
ctx = ctx.WithOutputFormat(conf.Output). | ||
WithChainID(conf.ChainID) | ||
|
||
keyring, err := client.NewKeyringFromBackend(ctx, conf.KeyringBackend) | ||
if err != nil { | ||
return ctx, fmt.Errorf("couldn't get key ring: %v", err) | ||
} | ||
|
||
ctx = ctx.WithKeyring(keyring) | ||
|
||
// https://github.com/cosmos/cosmos-sdk/issues/8986 | ||
client, err := client.NewClientFromNode(conf.Node) | ||
if err != nil { | ||
return ctx, fmt.Errorf("couldn't get client from nodeURI: %v", err) | ||
} | ||
|
||
ctx = ctx.WithNodeURI(conf.Node). | ||
WithClient(client). | ||
WithBroadcastMode(conf.BroadcastMode) | ||
|
||
return ctx, nil | ||
} |
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 |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package config | ||
|
||
import ( | ||
"bytes" | ||
"io/ioutil" | ||
"os" | ||
"text/template" | ||
|
||
"github.com/spf13/viper" | ||
) | ||
|
||
const defaultConfigTemplate = `# This is a TOML config file. | ||
# For more information, see https://github.com/toml-lang/toml | ||
|
||
############################################################################### | ||
### Client Configuration ### | ||
############################################################################### | ||
|
||
# The network chain ID | ||
chain-id = "{{ .ChainID }}" | ||
# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory) | ||
keyring-backend = "{{ .KeyringBackend }}" | ||
# CLI output format (text|json) | ||
output = "{{ .Output }}" | ||
# <host>:<port> to Tendermint RPC interface for this chain | ||
node = "{{ .Node }}" | ||
# Transaction broadcasting mode (sync|async|block) | ||
broadcast-mode = "{{ .BroadcastMode }}" | ||
` | ||
|
||
// writeConfigToFile parses defaultConfigTemplate, renders config using the template and writes it to | ||
// configFilePath. | ||
func writeConfigToFile(configFilePath string, config *ClientConfig) error { | ||
var buffer bytes.Buffer | ||
|
||
tmpl := template.New("clientConfigFileTemplate") | ||
configTemplate, err := tmpl.Parse(defaultConfigTemplate) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := configTemplate.Execute(&buffer, config); err != nil { | ||
return err | ||
} | ||
|
||
return ioutil.WriteFile(configFilePath, buffer.Bytes(), 0600) | ||
alessio marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
// ensureConfigPath creates a directory configPath if it does not exist | ||
func ensureConfigPath(configPath string) error { | ||
return os.MkdirAll(configPath, os.ModePerm) | ||
} | ||
|
||
// getClientConfig reads values from client.toml file and unmarshalls them into ClientConfig | ||
func getClientConfig(configPath string, v *viper.Viper) (*ClientConfig, error) { | ||
v.AddConfigPath(configPath) | ||
v.SetConfigName("client") | ||
v.SetConfigType("toml") | ||
|
||
if err := v.ReadInConfig(); err != nil { | ||
return nil, err | ||
} | ||
|
||
conf := new(ClientConfig) | ||
if err := v.Unmarshal(conf); err != nil { | ||
return nil, err | ||
} | ||
|
||
return conf, nil | ||
} |
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
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.
From my perspective, the code L96-L99 is redundant. We reuse the same code in ReadHomeFlag. That's why I have decided to remove it.