Context: Remove Init/New (#6797)

* init commit

* remove new/init functions

* update CLI commands

* tests: fix TestCLIQueryConn

* remove viper
This commit is contained in:
Alexander Bezobchuk 2020-07-20 12:42:46 -04:00 committed by GitHub
parent cde3f46d52
commit 515b25b94e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 85 additions and 267 deletions

View File

@ -1,24 +1,19 @@
package client
import (
"bufio"
"encoding/json"
"fmt"
"io"
"os"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/pkg/errors"
"github.com/spf13/viper"
yaml "gopkg.in/yaml.v2"
"github.com/tendermint/tendermint/libs/cli"
tmlite "github.com/tendermint/tendermint/lite"
rpcclient "github.com/tendermint/tendermint/rpc/client"
rpchttp "github.com/tendermint/tendermint/rpc/client/http"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -56,126 +51,6 @@ type Context struct {
Codec *codec.Codec
}
// TODO: Remove all New* and Init* methods.
// NewContextWithInputAndFrom returns a new initialized Context with parameters from the
// command line using Viper. It takes a io.Reader and and key name or address and populates
// the FromName and FromAddress field accordingly. It will also create Tendermint verifier
// using the chain ID, home directory and RPC URI provided by the command line. If using
// a Context in tests or any non CLI-based environment, the verifier will not be created
// and will be set as nil because FlagTrustNode must be set.
func NewContextWithInputAndFrom(input io.Reader, from string) Context {
ctx := Context{}
return ctx.InitWithInputAndFrom(input, from)
}
// NewContextWithFrom returns a new initialized Context with parameters from the
// command line using Viper. It takes a key name or address and populates the FromName and
// FromAddress field accordingly. It will also create Tendermint verifier using
// the chain ID, home directory and RPC URI provided by the command line. If using
// a Context in tests or any non CLI-based environment, the verifier will not
// be created and will be set as nil because FlagTrustNode must be set.
func NewContextWithFrom(from string) Context {
return NewContextWithInputAndFrom(os.Stdin, from)
}
// NewContext returns a new initialized Context with parameters from the
// command line using Viper.
func NewContext() Context { return NewContextWithFrom(viper.GetString(flags.FlagFrom)) }
// InitWithInputAndFrom returns a new Context re-initialized from an existing
// Context with a new io.Reader and from parameter
func (ctx Context) InitWithInputAndFrom(input io.Reader, from string) Context {
input = bufio.NewReader(input)
var (
nodeURI string
rpc rpcclient.Client
err error
)
offline := viper.GetBool(flags.FlagOffline)
if !offline {
nodeURI = viper.GetString(flags.FlagNode)
if nodeURI != "" {
rpc, err = rpchttp.New(nodeURI, "/websocket")
if err != nil {
fmt.Printf("failted to get client: %v\n", err)
os.Exit(1)
}
}
}
trustNode := viper.GetBool(flags.FlagTrustNode)
ctx.Client = rpc
ctx.ChainID = viper.GetString(flags.FlagChainID)
ctx.Input = input
ctx.Output = os.Stdout
ctx.NodeURI = nodeURI
ctx.From = viper.GetString(flags.FlagFrom)
ctx.OutputFormat = viper.GetString(cli.OutputFlag)
ctx.Height = viper.GetInt64(flags.FlagHeight)
ctx.TrustNode = trustNode
ctx.UseLedger = viper.GetBool(flags.FlagUseLedger)
ctx.BroadcastMode = viper.GetString(flags.FlagBroadcastMode)
ctx.Simulate = viper.GetBool(flags.FlagDryRun)
ctx.Offline = offline
ctx.SkipConfirm = viper.GetBool(flags.FlagSkipConfirmation)
ctx.HomeDir = viper.GetString(flags.FlagHome)
ctx.GenerateOnly = viper.GetBool(flags.FlagGenerateOnly)
backend := viper.GetString(flags.FlagKeyringBackend)
if len(backend) == 0 {
backend = keyring.BackendMemory
}
kr, err := newKeyringFromFlags(ctx, backend)
if err != nil {
panic(fmt.Errorf("couldn't acquire keyring: %v", err))
}
fromAddress, fromName, err := GetFromFields(kr, from, ctx.GenerateOnly)
if err != nil {
fmt.Printf("failed to get from fields: %v\n", err)
os.Exit(1)
}
ctx.Keyring = kr
ctx.FromAddress = fromAddress
ctx.FromName = fromName
if offline {
return ctx
}
// create a verifier for the specific chain ID and RPC client
verifier, err := CreateVerifier(ctx, DefaultVerifierCacheSize)
if err != nil && !trustNode {
fmt.Printf("failed to create verifier: %s\n", err)
os.Exit(1)
}
ctx.Verifier = verifier
return ctx
}
// InitWithFrom returns a new Context re-initialized from an existing
// Context with a new from parameter
func (ctx Context) InitWithFrom(from string) Context {
return ctx.InitWithInputAndFrom(os.Stdin, from)
}
// Init returns a new Context re-initialized from an existing
// Context with parameters from the command line using Viper.
func (ctx Context) Init() Context { return ctx.InitWithFrom(viper.GetString(flags.FlagFrom)) }
// InitWithInput returns a new Context re-initialized from an existing
// Context with a new io.Reader and from parameter
func (ctx Context) InitWithInput(input io.Reader) Context {
return ctx.InitWithInputAndFrom(input, viper.GetString(flags.FlagFrom))
}
// WithKeyring returns a copy of the context with an updated keyring.
func (ctx Context) WithKeyring(k keyring.Keyring) Context {
ctx.Keyring = k

View File

@ -10,7 +10,6 @@ import (
"github.com/cosmos/cosmos-sdk/testutil/testdata"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
@ -19,64 +18,6 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
)
func TestContext_WithOffline(t *testing.T) {
viper.Set(flags.FlagOffline, true)
viper.Set(flags.FlagNode, "tcp://localhost:26657")
ctx := client.NewContext()
require.True(t, ctx.Offline)
require.Nil(t, ctx.Client)
}
func TestContext_WithGenOnly(t *testing.T) {
viper.Set(flags.FlagGenerateOnly, true)
validFromAddr := "cosmos1q7380u26f7ntke3facjmynajs4umlr329vr4ja"
fromAddr, err := sdk.AccAddressFromBech32(validFromAddr)
require.NoError(t, err)
tests := []struct {
name string
from string
expectedFromAddr sdk.AccAddress
expectedFromName string
}{
{
name: "valid from",
from: validFromAddr,
expectedFromAddr: fromAddr,
expectedFromName: "",
},
{
name: "empty from",
from: "",
expectedFromAddr: nil,
expectedFromName: "",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
ctx := client.NewContextWithFrom(tt.from)
require.Equal(t, tt.expectedFromAddr, ctx.FromAddress)
require.Equal(t, tt.expectedFromName, ctx.FromName)
})
}
}
func TestContext_WithKeyring(t *testing.T) {
viper.Set(flags.FlagGenerateOnly, true)
ctx := client.NewContextWithFrom("cosmos1q7380u26f7ntke3facjmynajs4umlr329vr4ja")
require.NotNil(t, ctx.Keyring)
kr := ctx.Keyring
ctx = ctx.WithKeyring(nil)
require.Nil(t, ctx.Keyring)
ctx = ctx.WithKeyring(kr)
require.Equal(t, kr, ctx.Keyring)
}
func TestMain(m *testing.M) {
viper.Set(flags.FlagKeyringBackend, keyring.BackendMemory)
os.Exit(m.Run())

View File

@ -7,7 +7,6 @@ import (
"github.com/gorilla/mux"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
@ -23,14 +22,36 @@ func BlockCommand() *cobra.Command {
Use: "block [height]",
Short: "Get verified data for a the block at given height",
Args: cobra.MaximumNArgs(1),
RunE: printBlock,
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
var height *int64
// optional height
if len(args) > 0 {
h, err := strconv.Atoi(args[0])
if err != nil {
return err
}
if h > 0 {
tmp := int64(h)
height = &tmp
}
}
output, err := getBlock(clientCtx, height)
if err != nil {
return err
}
fmt.Println(string(output))
return nil
},
}
cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
viper.BindPFlag(flags.FlagNode, cmd.Flags().Lookup(flags.FlagNode))
cmd.Flags().Bool(flags.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
viper.BindPFlag(flags.FlagTrustNode, cmd.Flags().Lookup(flags.FlagTrustNode))
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
viper.BindPFlag(flags.FlagKeyringBackend, cmd.Flags().Lookup(flags.FlagKeyringBackend))
return cmd
}
@ -83,33 +104,6 @@ func GetChainHeight(clientCtx client.Context) (int64, error) {
return height, nil
}
// CMD
func printBlock(cmd *cobra.Command, args []string) error {
var height *int64
// optional height
if len(args) > 0 {
h, err := strconv.Atoi(args[0])
if err != nil {
return err
}
if h > 0 {
tmp := int64(h)
height = &tmp
}
}
output, err := getBlock(client.NewContext(), height)
if err != nil {
return err
}
fmt.Println(string(output))
return nil
}
// REST
// REST handler to get a block
func BlockRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {

View File

@ -5,7 +5,6 @@ import (
"net/http"
"github.com/spf13/cobra"
"github.com/spf13/viper"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
@ -23,11 +22,26 @@ func StatusCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "status",
Short: "Query remote node for status",
RunE: printNodeStatus,
RunE: func(cmd *cobra.Command, _ []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
status, err := getNodeStatus(clientCtx)
if err != nil {
return err
}
output, err := legacy.Cdc.MarshalJSON(status)
if err != nil {
return err
}
fmt.Println(string(output))
return nil
},
}
cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
viper.BindPFlag(flags.FlagNode, cmd.Flags().Lookup(flags.FlagNode))
return cmd
}
@ -40,27 +54,6 @@ func getNodeStatus(clientCtx client.Context) (*ctypes.ResultStatus, error) {
return node.Status()
}
func printNodeStatus(_ *cobra.Command, _ []string) error {
// No need to verify proof in getting node status
viper.Set(flags.FlagTrustNode, true)
// No need to verify proof in getting node status
viper.Set(flags.FlagKeyringBackend, flags.DefaultKeyringBackend)
clientCtx := client.NewContext()
status, err := getNodeStatus(clientCtx)
if err != nil {
return err
}
output, err := legacy.Cdc.MarshalJSON(status)
if err != nil {
return err
}
fmt.Println(string(output))
return nil
}
// NodeInfoResponse defines a response type that contains node status and version
// information.
type NodeInfoResponse struct {
@ -81,6 +74,7 @@ func NodeInfoRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
DefaultNodeInfo: status.NodeInfo,
ApplicationVersion: version.NewInfo(),
}
rest.PostProcessResponseBare(w, clientCtx, resp)
}
}

View File

@ -144,6 +144,8 @@ func interceptConfigs(ctx *Context, rootViper *viper.Viper) (*tmcfg.Config, erro
}
}
conf.SetRoot(rootDir)
appConfigFilePath := filepath.Join(configPath, "app.toml")
if _, err := os.Stat(appConfigFilePath); os.IsNotExist(err) {
appConf, err := config.ParseConfig(ctx.Viper)

View File

@ -1,5 +1,3 @@
// +build cli_test
package cli
import (
@ -8,20 +6,18 @@ import (
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/testutil/network"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
)
func TestCliQueryConn(t *testing.T) {
t.Parallel()
f := NewFixtures(t)
func TestCLIQueryConn(t *testing.T) {
cfg := network.DefaultConfig()
cfg.NumValidators = 1
// start simd server
proc := f.SDStart()
t.Cleanup(func() { proc.Stop(false) })
n := network.New(t, cfg)
defer n.Cleanup()
ctx := client.NewContext()
testClient := testdata.NewTestServiceClient(ctx)
testClient := testdata.NewTestServiceClient(n.Validators[0].ClientCtx)
res, err := testClient.Echo(context.Background(), &testdata.EchoRequest{Message: "hello"})
require.NoError(t, err)
require.Equal(t, "hello", res.Message)

View File

@ -188,7 +188,7 @@ func TestProcessPostResponse(t *testing.T) {
// setup
viper.Set(flags.FlagOffline, true)
ctx := client.NewContext()
ctx := client.Context{}
height := int64(194423)
privKey := secp256k1.GenPrivKey()

View File

@ -12,7 +12,7 @@ import (
// modules, under a sub-command. This allows external modules to implement custom
// Evidence types and Handlers while having the ability to create and sign txs
// containing them all from a single root command.
func GetTxCmd(clientCtx client.Context, childCmds []*cobra.Command) *cobra.Command {
func GetTxCmd(childCmds []*cobra.Command) *cobra.Command {
cmd := &cobra.Command{
Use: types.ModuleName,
Short: "Evidence transaction subcommands",
@ -21,7 +21,7 @@ func GetTxCmd(clientCtx client.Context, childCmds []*cobra.Command) *cobra.Comma
RunE: client.ValidateCmd,
}
submitEvidenceCmd := SubmitEvidenceCmd(clientCtx)
submitEvidenceCmd := SubmitEvidenceCmd()
for _, childCmd := range childCmds {
submitEvidenceCmd.AddCommand(childCmd)
}
@ -34,7 +34,7 @@ func GetTxCmd(clientCtx client.Context, childCmds []*cobra.Command) *cobra.Comma
// SubmitEvidenceCmd returns the top-level evidence submission command handler.
// All concrete evidence submission child command handlers should be registered
// under this command.
func SubmitEvidenceCmd(_ client.Context) *cobra.Command {
func SubmitEvidenceCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "submit",
Short: "Submit arbitrary evidence of misbehavior",

View File

@ -12,7 +12,7 @@ type (
RESTHandlerFn func(client.Context) rest.EvidenceRESTHandler
// CLIHandlerFn defines a CLI command handler for evidence submission
CLIHandlerFn func(client.Context) *cobra.Command
CLIHandlerFn func() *cobra.Command
// EvidenceHandler defines a type that exposes REST and CLI client handlers for
// evidence submission.

View File

@ -86,14 +86,14 @@ func (a AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Ro
}
// GetTxCmd returns the evidence module's root tx command.
func (a AppModuleBasic) GetTxCmd(clientCtx client.Context) *cobra.Command {
func (a AppModuleBasic) GetTxCmd(_ client.Context) *cobra.Command {
evidenceCLIHandlers := make([]*cobra.Command, len(a.evidenceHandlers))
for i, evidenceHandler := range a.evidenceHandlers {
evidenceCLIHandlers[i] = evidenceHandler.CLIHandler(clientCtx)
evidenceCLIHandlers[i] = evidenceHandler.CLIHandler()
}
return cli.GetTxCmd(clientCtx, evidenceCLIHandlers)
return cli.GetTxCmd(evidenceCLIHandlers)
}
// GetQueryCmd returns the evidence module's root query command.

View File

@ -95,8 +95,7 @@ func TestInitCmd(t *testing.T) {
}
func setupClientHome(t *testing.T) func() {
clientDir, cleanup := testutil.NewTestCaseDir(t)
viper.Set(cli.HomeFlag, clientDir)
_, cleanup := testutil.NewTestCaseDir(t)
return cleanup
}

View File

@ -162,7 +162,11 @@ $ %s tx staking delegate cosmosvaloper1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm 10
),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := clientCtx.InitWithInput(cmd.InOrStdin())
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
}
amount, err := sdk.ParseCoin(args[1])
if err != nil {
@ -204,7 +208,11 @@ $ %s tx staking redelegate cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := clientCtx.InitWithInput(cmd.InOrStdin())
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
}
delAddr := clientCtx.GetFromAddress()
valSrcAddr, err := sdk.ValAddressFromBech32(args[0])
@ -251,7 +259,11 @@ $ %s tx staking unbond cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 100s
),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := clientCtx.InitWithInput(cmd.InOrStdin())
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
}
delAddr := clientCtx.GetFromAddress()
valAddr, err := sdk.ValAddressFromBech32(args[0])

View File

@ -91,14 +91,19 @@ func NewCmdSubmitUpgradeProposal() *cobra.Command {
}
// NewCmdSubmitCancelUpgradeProposal implements a command handler for submitting a software upgrade cancel proposal transaction.
func NewCmdSubmitCancelUpgradeProposal(clientCtx client.Context) *cobra.Command {
func NewCmdSubmitCancelUpgradeProposal() *cobra.Command {
cmd := &cobra.Command{
Use: "cancel-software-upgrade [flags]",
Args: cobra.ExactArgs(0),
Short: "Submit a software upgrade proposal",
Long: "Cancel a software upgrade along with an initial deposit.",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := clientCtx.InitWithInput(cmd.InOrStdin())
clientCtx := client.GetClientContextFromCmd(cmd)
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
}
from := clientCtx.GetFromAddress()
depositStr, err := cmd.Flags().GetString(cli.FlagDeposit)