fix: bind values from env variables to flags (#8337)

allows clients access values in env variables

Signed-off-by: Artur Troian <troian.ap@gmail.com>
This commit is contained in:
Artur Troian 2021-01-28 20:58:44 -05:00 committed by GitHub
parent 034d140488
commit c252a60ff8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 0 deletions

View File

@ -108,6 +108,24 @@ Flags are added to commands directly (generally in the [module's CLI file](../bu
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L118
## Environment variables
Each flag is bound to it's respecteve named environment variable. Then name of the environment variable consist of two parts - capital case `basename` followed by flag name of the flag. `-` must be substituted with `_`. For example flag `--home` for application with basename `GAIA` is bound to `GAIA_HOME`. It allows to reduce amount of flags typed for routine operations. For example instead of:
```sh
gaia --home=./ --node=<node address> --chain-id="testchain-1" --keyring-backend=test tx ... --from=<key name>
```
this will be more convinient:
```sh
# define env variables in .env, .envrc etc
GAIA_HOME=<path to home>
GAIA_NODE=<node address>
GAIA_CHAIN_ID="testchain-1"
GAIA_KEYRING_BACKEND="test"
# and later just use
gaia tx ... --from=<key name>
```
## Configurations
It is vital that the root command of an application uses `PersistentPreRun()` cobra command property for executing the command, so all child commands have access to the server and client contexts. These contexts are set as their default values initially and maybe modified, scoped to the command, in their respective `PersistentPreRun()` functions. Note that the `client.Context` is typically pre-populated with "default" values that may be useful for all commands to inherit and override if necessary.

View File

@ -17,6 +17,7 @@ import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
tmcfg "github.com/tendermint/tendermint/config"
tmlog "github.com/tendermint/tendermint/libs/log"
@ -63,6 +64,37 @@ func NewContext(v *viper.Viper, config *tmcfg.Config, logger tmlog.Logger) *Cont
return &Context{v, config, logger}
}
func bindFlags(basename string, cmd *cobra.Command, v *viper.Viper) (err error) {
defer func() {
recover()
}()
cmd.Flags().VisitAll(func(f *pflag.Flag) {
// Environment variables can't have dashes in them, so bind them to their equivalent
// keys with underscores, e.g. --favorite-color to STING_FAVORITE_COLOR
err = v.BindEnv(f.Name, fmt.Sprintf("%s_%s", basename, strings.ToUpper(strings.ReplaceAll(f.Name, "-", "_"))))
if err != nil {
panic(err)
}
err = v.BindPFlag(f.Name, f)
if err != nil {
panic(err)
}
// Apply the viper config value to the flag when the flag is not set and viper has a value
if !f.Changed && v.IsSet(f.Name) {
val := v.Get(f.Name)
err = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val))
if err != nil {
panic(err)
}
}
})
return
}
// InterceptConfigsPreRunHandler performs a pre-run function for the root daemon
// application command. It will create a Viper literal and a default server
// Context. The server Tendermint configuration will either be read and parsed
@ -98,6 +130,9 @@ func InterceptConfigsPreRunHandler(cmd *cobra.Command) error {
// return value is a tendermint configuration object
serverCtx.Config = config
if err = bindFlags(basename, cmd, serverCtx.Viper); err != nil {
return err
}
var logWriter io.Writer
if strings.ToLower(serverCtx.Viper.GetString(flags.FlagLogFormat)) == tmcfg.LogFormatPlain {