diff --git a/client/config/config_test.go b/client/config/config_test.go new file mode 100644 index 0000000000..c058edf830 --- /dev/null +++ b/client/config/config_test.go @@ -0,0 +1,107 @@ +package config_test + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/config" + "github.com/cosmos/cosmos-sdk/client/flags" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/x/staking/client/cli" +) + +const ( + nodeEnv = "NODE" + testNode1 = "http://localhost:1" + testNode2 = "http://localhost:2" +) + +// initClientContext initiates client Context for tests +func initClientContext(t *testing.T, envVar string) (client.Context, func()) { + home := t.TempDir() + clientCtx := client.Context{}. + WithHomeDir(home). + WithViper("") + + clientCtx.Viper.BindEnv(nodeEnv) + if envVar != "" { + os.Setenv(nodeEnv, envVar) + } + + clientCtx, err := config.ReadFromClientConfig(clientCtx) + require.NoError(t, err) + + return clientCtx, func() { _ = os.RemoveAll(home) } +} + +func TestConfigCmd(t *testing.T) { + clientCtx, cleanup := initClientContext(t, testNode1) + defer func() { + os.Unsetenv(nodeEnv) + cleanup() + }() + + // NODE=http://localhost:1 ./build/simd config node http://localhost:2 + cmd := config.Cmd() + args := []string{"node", testNode2} + _, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) + require.NoError(t, err) + + //./build/simd config node //http://localhost:1 + b := bytes.NewBufferString("") + cmd.SetOut(b) + cmd.SetArgs([]string{"node"}) + cmd.Execute() + out, err := ioutil.ReadAll(b) + require.NoError(t, err) + require.Equal(t, string(out), testNode1+"\n") +} + +func TestConfigCmdEnvFlag(t *testing.T) { + const ( + defaultNode = "http://localhost:26657" + ) + + tt := []struct { + name string + envVar string + args []string + expNode string + }{ + {"env var is set with no flag", testNode1, []string{"validators"}, testNode1}, + {"env var is set with a flag", testNode1, []string{"validators", fmt.Sprintf("--%s=%s", flags.FlagNode, testNode2)}, testNode2}, + {"env var is not set with no flag", "", []string{"validators"}, defaultNode}, + {"env var is not set with a flag", "", []string{"validators", fmt.Sprintf("--%s=%s", flags.FlagNode, testNode2)}, testNode2}, + } + + for _, tc := range tt { + tc := tc + t.Run(tc.name, func(t *testing.T) { + clientCtx, cleanup := initClientContext(t, tc.envVar) + defer func() { + if tc.envVar != "" { + os.Unsetenv(nodeEnv) + } + cleanup() + }() + /* + env var is set with a flag + + NODE=http://localhost:1 ./build/simd q staking validators --node http://localhost:2 + Error: post failed: Post "http://localhost:2": dial tcp 127.0.0.1:2: connect: connection refused + + We dial http://localhost:2 cause a flag has the higher priority than env variable. + */ + cmd := cli.GetQueryCmd() + _, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + require.Error(t, err) + require.Contains(t, err.Error(), tc.expNode, "Output does not contain expected Node") + }) + } +} diff --git a/client/context.go b/client/context.go index 4dbdb97f02..844b434bd5 100644 --- a/client/context.go +++ b/client/context.go @@ -227,8 +227,10 @@ func (ctx Context) WithInterfaceRegistry(interfaceRegistry codectypes.InterfaceR // WithViper returns the context with Viper field. This Viper instance is used to read // client-side config from the config file. -func (ctx Context) WithViper() Context { +func (ctx Context) WithViper(prefix string) Context { v := viper.New() + v.SetEnvPrefix(prefix) + v.AutomaticEnv() ctx.Viper = v return ctx } diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index 30356d3ed5..ebb69b47c5 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -47,7 +47,7 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) { WithAccountRetriever(types.AccountRetriever{}). WithBroadcastMode(flags.BroadcastBlock). WithHomeDir(simapp.DefaultNodeHome). - WithViper() + WithViper("") // In simapp, we don't use any prefix for env variables. rootCmd := &cobra.Command{ Use: "simd",