Skip to content
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 #8820

Closed
2 changes: 1 addition & 1 deletion client/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont
keyringBackend, _ := flagSet.GetString(flags.FlagKeyringBackend)

if keyringBackend != "" {
kr, err := newKeyringFromFlags(clientCtx, keyringBackend)
kr, err := NewKeyringFromFlags(clientCtx, keyringBackend)
if err != nil {
return clientCtx, err
}
Expand Down
119 changes: 119 additions & 0 deletions client/config/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package config

import (
"encoding/json"
"errors"
"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")

if err := ensureConfigPath(configPath); err != nil {
return fmt.Errorf("couldn't make client config: %v", err)
}

cliConfig, 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(cliConfig, "", "\t")
cmd.Println(string(s))

case 1:
// it's a get
// TODO implement method for get
// should i implement getters here?
key := args[0]
switch key {
case flags.FlagChainID:
cmd.Println(cliConfig.ChainID)
case flags.FlagKeyringBackend:
cmd.Println(cliConfig.KeyringBackend)
case tmcli.OutputFlag:
cmd.Println(cliConfig.Output)
case flags.FlagNode:
cmd.Println(cliConfig.Node)
case flags.FlagBroadcastMode:
cmd.Println(cliConfig.BroadcastMode)
// case "trace":
// cmd.Println(cliConfig.Trace)
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:
cliConfig.SetChainID(value)
case flags.FlagKeyringBackend:
cliConfig.SetKeyringBackend(value)
case tmcli.OutputFlag:
cliConfig.SetOutput(value)
case flags.FlagNode:
cliConfig.SetNode(value)
case flags.FlagBroadcastMode:
cliConfig.SetBroadcastMode(value)
/*
case "trace":
if err := cliConfig.SetTrace(value); err != nil {
return fmt.Errorf("couldn't parse bool value: %v", err)
}
*/
default:
return errUnknownConfigKey(key)
}

configTemplate, err := initConfigTemplate()
if err != nil {
return fmt.Errorf("could not initiate config template: %v", err)
}

cliConfigFile := filepath.Join(configPath, "client.toml")
if err := writeConfigFile(cliConfigFile, cliConfig, configTemplate); err != nil {
return fmt.Errorf("could not write client config to the file: %v", err)
}

default:
// print error
return errors.New("cound not execute config command")
}

return nil
}

func errUnknownConfigKey(key string) error {
return fmt.Errorf("unknown configuration key: %q", key)
}
140 changes: 30 additions & 110 deletions client/config/config.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
package config

import (
"encoding/json"
"errors"
"fmt"
// "fmt"
"path/filepath"
"strconv"

"github.com/spf13/cobra"

tmcli "github.com/tendermint/tendermint/libs/cli"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
)

// Default constants
Expand All @@ -22,21 +14,23 @@ const (
output = "text"
node = "tcp://localhost:26657"
broadcastMode = "sync"
trace = false
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
)

var ErrWrongNumberOfArgs = fmt.Errorf("wrong number of arguments")
// trace = false
)

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"`
Trace bool `mapstructure:"trace" json:"trace"`
// Trace bool `mapstructure:"trace" json:"trace"`
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
}

func DefaultClientConfig() *ClientConfig {
return &ClientConfig{chainID, keyringBackend, output, node, broadcastMode}
}

// TODO Validate values in setters
func (c *ClientConfig) SetChainID(chainID string) {
c.ChainID = chainID
}
Expand All @@ -57,6 +51,7 @@ func (c *ClientConfig) SetBroadcastMode(broadcastMode string) {
c.BroadcastMode = broadcastMode
}

/*
func (c *ClientConfig) SetTrace(trace string) error {
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
boolVal, err := strconv.ParseBool(trace)
if err != nil {
Expand All @@ -65,112 +60,37 @@ func (c *ClientConfig) SetTrace(trace string) error {
c.Trace = boolVal
return nil
}
*/

func DefaultClientConfig() *ClientConfig {
return &ClientConfig{chainID, keyringBackend, output, node, broadcastMode, trace}
}

// Cmd returns a CLI command to interactively create an application CLI
// config file.
func Cmd(defaultCLIHome string) *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),
}

cmd.Flags().String(flags.FlagHome, defaultCLIHome,
"set client's home directory for configuration")
return cmd
}

func runConfigCmd(cmd *cobra.Command, args []string) error {
func UpdateClientContextFromClientConfig(ctx client.Context) client.Context {
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
configPath := filepath.Join(ctx.HomeDir, "config")

clientCtx := client.GetClientContextFromCmd(cmd)

configPath := filepath.Join(clientCtx.HomeDir, "config")

if err := ensureConfigPath(configPath); err != nil {
return fmt.Errorf("couldn't make config config: %v", err)
}

cliConfig, 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(cliConfig, "", "\t")
cmd.Println(string(s))

case 1:
// it's a get
// TODO implement method for get
// should i implement getters here?
key := args[0]
switch key {
case flags.FlagChainID:
cmd.Println(cliConfig.ChainID)
case flags.FlagKeyringBackend:
cmd.Println(cliConfig.KeyringBackend)
case tmcli.OutputFlag:
cmd.Println(cliConfig.Output)
case flags.FlagNode:
cmd.Println(cliConfig.Node)
case flags.FlagBroadcastMode:
cmd.Println(cliConfig.BroadcastMode)
case "trace":
cmd.Println(cliConfig.Trace)
default:
err := errUnknownConfigKey(key)
return fmt.Errorf("couldn't get the value for the key: %v, error: %v\n", key, err)
/*
if err := ensureConfigPath(configPath); err != nil {
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
return ctx, fmt.Errorf("couldn't make client config: %v", err)
}

case 2:
// it's set

key, value := args[0], args[1]

switch key {
case flags.FlagChainID:
cliConfig.SetChainID(value)
case flags.FlagKeyringBackend:
cliConfig.SetKeyringBackend(value)
case tmcli.OutputFlag:
cliConfig.SetOutput(value)
case flags.FlagNode:
cliConfig.SetNode(value)
case flags.FlagBroadcastMode:
cliConfig.SetBroadcastMode(value)
case "trace":
if err := cliConfig.SetTrace(value); err != nil {
return fmt.Errorf("couldn't parse bool value: %v", err)
}
default:
return errUnknownConfigKey(key)
cliConfig, err := getClientConfig(configPath, ctx.Viper)
if err != nil {
return ctx, fmt.Errorf("couldn't get client config: %v", err)
}

configTemplate, err := InitConfigTemplate()

keyRing, err := client.NewKeyringFromFlags(ctx, cliConfig.KeyringBackend)
if err != nil {
return fmt.Errorf("could not initiate config template: %v", err)
return ctx, fmt.Errorf("couldn't get key ring: %v", err)
}
*/

cliConfigFile := filepath.Join(configPath, "client.toml")
if err := WriteConfigFile(cliConfigFile, cliConfig, configTemplate); err != nil {
return fmt.Errorf("could not write client config to the file: %v", err)
}
cliConfig, _ := getClientConfig(configPath, ctx.Viper)

default:
// print error
return errors.New("cound not execute config command")
}
keyRing, _ := client.NewKeyringFromFlags(ctx, cliConfig.KeyringBackend)
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved

return nil
}
ctx = ctx.WithChainID(cliConfig.ChainID).
WithKeyring(keyRing).
WithOutputFormat(cliConfig.Output).
WithNodeURI(cliConfig.Node).
WithBroadcastMode(cliConfig.BroadcastMode)

func errUnknownConfigKey(key string) error {
return fmt.Errorf("unknown configuration key: %q", key)
return ctx
}
18 changes: 9 additions & 9 deletions client/config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
package config

import (
"errors"
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/cosmos/cosmos-sdk/client/flags"
)

var ErrWrongNumberOfArgs = errors.New("wrong number of arguments")

// For https://github.com/cosmos/cosmos-sdk/issues/3899
func Test_runConfigCmdTwiceWithShorterNodeValue(t *testing.T) {
// Prepare environment
t.Parallel()
configHome, cleanup := tmpDir(t)
cleanup := tmpDir(t)
defer cleanup()
_ = os.RemoveAll(filepath.Join(configHome, "config"))
viper.Set(flags.FlagHome, configHome)
_ = os.RemoveAll(filepath.Join("config"))

// Init command config
cmd := Cmd(configHome)
cmd := Cmd()
assert.NotNil(t, cmd)

err := cmd.RunE(cmd, []string{"node", "tcp://localhost:26657"})
Expand Down Expand Up @@ -51,11 +50,12 @@ func Test_runConfigCmdTwiceWithShorterNodeValue(t *testing.T) {
require.Equal(t, err, errUnknownConfigKey("invalidKey"))

// TODO add testing of pririty environmental variable, flag and file
// for now manual testign is ok

}

func tmpDir(t *testing.T) (string, func()) {
func tmpDir(t *testing.T) func() {
dir, err := ioutil.TempDir("", t.Name()+"_")
require.NoError(t, err)
return dir, func() { _ = os.RemoveAll(dir) }
return func() { _ = os.RemoveAll(dir) }
}
Loading