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

Conversation

cyberbono3
Copy link
Contributor

@cyberbono3 cyberbono3 commented Mar 9, 2021

Description

This is draft PR that implements Step1 from #8529

Step 1 Creating a new $NODE_DIR/config/client.toml file to hold all client-side configuration (e.g. keyring-backend, node, chain-id etc...).

Questions:

  1. Do i need to include all flags into client config?
  2. Do we want print default value if key is invalid in case of get flag is set here?
  3. Do I need to check if our key matches one of these values?

@AmauryM Could you leave your feedback, please?


Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.

  • Targeted PR against correct branch (see CONTRIBUTING.md)
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the module structure standards.
  • Wrote unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Added relevant godoc comments.
  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer
  • Review Codecov Report in the comment section below once CI passes

@cyberbono3 cyberbono3 force-pushed the cyberbono3/8529-add-client-config branch from 0071d76 to aecceec Compare March 9, 2021 17:06
client/config/config.go Outdated Show resolved Hide resolved
@@ -92,220 +48,104 @@ func Cmd(defaultCLIHome string) *cobra.Command {

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")
// cmd.Flags().Bool(flagGet, false,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we dont need a flagGet flag here, do we?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's correct! as per Alessio's proposal #8820 (comment)

if err != nil {
return fmt.Errorf("Unable to get client config %v", err)
fmt.Fprintf(os.Stderr, "Unable to get client config: %v\n", err)
return err
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alessio Following your suggestion, I print an error here to os.Stderr. I am unable to add os.Exit(1) cause the runConfigCmd is supposed to return an error.

client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
client/config/toml.go Outdated Show resolved Hide resolved
client/config/toml.go Outdated Show resolved Hide resolved
client/config/toml.go Outdated Show resolved Hide resolved
server/util.go Outdated Show resolved Hide resolved
@cyberbono3 cyberbono3 force-pushed the cyberbono3/8529-add-client-config branch from af6f2a1 to 8dbc688 Compare March 10, 2021 19:38
Copy link
Contributor Author

@cyberbono3 cyberbono3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need more context on adding testing of priority env variable, flag and file.

Additionally, I have added my config subcommand here to rootCmd. I hope it makes sence.

server/util.go Outdated Show resolved Hide resolved
@@ -92,220 +48,104 @@ func Cmd(defaultCLIHome string) *cobra.Command {

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")
// cmd.Flags().Bool(flagGet, false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's correct! as per Alessio's proposal #8820 (comment)

client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
client/config/toml.go Outdated Show resolved Hide resolved
client/config/toml.go Outdated Show resolved Hide resolved
client/config/toml.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
@cyberbono3
Copy link
Contributor Author

To improve code readability I would like to move all cmd logic to new cmd.go file . In config.go I leave only logic associated with client config. Does it sound good?

@cyberbono3
Copy link
Contributor Author

Another suggestion would be to implement separate function or 2 functions to handle get and set cases in runConfigCmd.

@cyberbono3
Copy link
Contributor Author

I tried to test my code . I removed everything from ~/.simapp and ran this shell script. Unfortunately, client.toml has not been created. Is it proper way to test it or there is another way to do it(e.g. integration testing)?

@alessio
Copy link
Contributor

alessio commented Mar 12, 2021 via email

@cyberbono3
Copy link
Contributor Author

./build/simd init moniker --chain-id sss
I am able to write the client config into client.toml. Thanks @clevinson for help.

@cyberbono3 cyberbono3 force-pushed the cyberbono3/8529-add-client-config branch from f9f22da to f4f6dde Compare March 15, 2021 03:58
client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
@cyberbono3
Copy link
Contributor Author

cyberbono3 commented Mar 16, 2021

@alessio I have question regarding interceptConfigs. I use viper field rootViper from serverCtx here . This is my code associated with my client config inserted into interceptConfigs. Does it make sense to decouple server config and client config logic? Should I use different Viper fields for server and client config?

@cyberbono3
Copy link
Contributor Author

@alessio @AmauryM mentioned here:

Step 2 (for 0.43+). Think about refactoring config as a whole, with the objectives in mind to: remove dependency on singletons make sure we have the exact same configurable variables via flags, ENV variables and config file, and define a priority between them when multiple are set

I would like to start working on Step 2 (second PR) . I need more context regarding it.

which dependency on singleton should be removed?
How we set priorities between ENV variables, flags and config file?

@alexanderbez
Copy link
Contributor

alexanderbez commented Mar 16, 2021

How we set priorities between ENV variables, flags and config file?

flags > env vars > config file, this is typically the standard.

@amaury1093
Copy link
Contributor

which dependency on singleton should be removed?

Example:

if viper.GetBool(flagNoAutoIncrement) {
. There might be others.

@alessio
Copy link
Contributor

alessio commented Mar 16, 2021

How we set priorities between ENV variables, flags and config file?

flags > env vars > config file, this is typically the standard.

Mmm... I think flags should override env vars, and both override config files. Is that correct?

client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
@cyberbono3
Copy link
Contributor Author

cyberbono3 commented Mar 18, 2021

Priority rule flags > env vars > config file

I have performed some manual tests. I hope I have performed them right. Otherwise, please advice.

This is my initial client config
./build/simd config
{ "chain-id": "", "keyring-backend": "os", "output": "text", "node": "tcp://localhost:26657", "broadcast-mode": "sync" }
Manual tests:

  1. env variable and config

NODE=tcp://localhost:26658
./build/simd q bank total
Error: post failed: Post "http://localhost:26657": dial tcp 127.0.0.1:26657: connect: connection refused

Conclusion: Test does not pass, it should dial tcp://localhost:26658 cause env variable has higher priority than config

  1. flag and config

./build/simd q bank total --node tcp://localhost:26658
Error: post failed: Post "http://localhost:26658": dial tcp 127.0.0.1:26658: connect: connection refused

Conclusion : test pass cause flag has the highest priority

  1. flag, env var and config

NODE=tcp://localhost:26658
./build/simd q bank total --node tcp://localhost:26659
Error: post failed: Post "http://localhost:26659": dial tcp 127.0.0.1:26659: connect: connection refused

Conclusion: test pass cause flag has the highest priority

  1. change config node to tcp://localhost:26500 and call ./build/simd q bank total

./build/simd config node tcp://localhost:26500
./build/simd config node
tcp://localhost:26500

./build/simd q bank total
Error: post failed: Post "http://localhost:26657": dial tcp 127.0.0.1:26657: connect: connection refused

Conclusion: test does not pass cause it should dial the node from config file tcp://localhost:26500
right?

rootCmd := &cobra.Command{
Use: "simd",
Short: "simulation app",
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {

Copy link
Contributor Author

@cyberbono3 cyberbono3 Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have also tried to put clicfg.UpdateClientContextFromClientConfig(initClientCtx) inside PersistentPreRunE. In this case I can handle an error occured by reading from client.toml file. I have got the same test results.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put inside PersistentPreRunE then.

The docs say that this function:

 PersistentPreRun: children of this command will inherit and execute.

So I guess it's what we want.

@cyberbono3
Copy link
Contributor Author

cyberbono3 commented Mar 18, 2021

It seems, Vyper does not read env variables from linux terminal. It has AutomaticEnv() function which can read env variables from the config file only. Alternatively, os.GetEnv(varname) can be used.

Copy link
Contributor

@amaury1093 amaury1093 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The manual tests you performed looks good to me.

I think with the UpdateClientContextFromClientConfig function, we're getting close! Thanks @cyberbono3

Inside that function, imo we also need to add a logic saying:

  • make sure the config path & file exist
  • if the config file doesn't exist, create a new one and populate it with default values

I can have a look at the viper reading from terminal env vars issue.

client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
client/config/config.go Outdated Show resolved Hide resolved
@@ -0,0 +1,189 @@
# This is a TOML config file.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong committed file?

rootCmd := &cobra.Command{
Use: "simd",
Short: "simulation app",
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put inside PersistentPreRunE then.

The docs say that this function:

 PersistentPreRun: children of this command will inherit and execute.

So I guess it's what we want.

@@ -323,7 +334,7 @@ func GetFromFields(kr keyring.Keyring, from string, genOnly bool) (sdk.AccAddres
return info.GetAddress(), info.GetName(), info.GetType(), nil
}

func newKeyringFromFlags(ctx Context, backend string) (keyring.Keyring, error) {
func NewKeyringFromFlags(ctx Context, backend string) (keyring.Keyring, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe NewKeyringFromString or NewKeyringFromBackend are both more correct names, and can be used in the toml file logic without sounding confusing.

client/config/config.go Show resolved Hide resolved
@cyberbono3 cyberbono3 force-pushed the cyberbono3/8529-add-client-config branch from f49f07a to 8125d5e Compare March 18, 2021 22:29
@cyberbono3
Copy link
Contributor Author

cyberbono3 commented Mar 18, 2021

Manual testing 2

0../build/simd init andrei
Outcome: client.toml created inside ~/.simapp/config

  1. ./build/simd config node http://localhost:2666
    Outcome: http://localhost:2666
  2. './build/simd q bank total DOES NOT PASS
    Expected outcome: can not connect to http://localhost:2666
    Actual outcome: Error: post failed: Post "http://localhost:26657": dial tcp 127.0.0.1:26657: connect: connection refused
    ?
  3. ./build/simd q bank total --node http://localhost:2555
    Outcome: cannot connect to "http://localhost:2555"
  4. remove whole directory ~/.simapp and then run simd init moniker
    Outcome client.toml is created ~/.simapp/config in with default values
    DONE
    PASS

TODO
Perform these steps for another field from client.toml
let do keyring-backend (will not be in q bank total)

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we dont need ensureConfigPath anymore, cause ~/.simapp/config directory will exist in any way due to ReadFromClientConfig logic

client/config/toml.go Outdated Show resolved Hide resolved
cd test/config there is no client.toml configuration file
*/

func (ctx Context) WithHomeFlag(cmd *cobra.Command) Context {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a bug by executing this command ./build/simd init andrei --home ./test. There is no client.toml created inside ./test/config. WithHomeFlag fixes this bug.

@@ -56,11 +55,12 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
Short: "simulation app",
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {

initClientCtx = initClientCtx.WithHomeFlag(cmd)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I move WithHomeFlag(cmd) inside config.ReadFromClientConfig to make our code a little bit cleaner?

@tac0turtle
Copy link
Member

super seeded by #8953

@tac0turtle tac0turtle closed this Mar 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants