Skip to content

Commit f8df05f

Browse files
amaury1093fedekunzemergify[bot]
authored
x/upgrade: Refactor CLI to use protobuf query (#6623)
* x/upgrade: Refactor CLI to use protobuf query * Import lint * Use table tests * Small tweak in setup * Address bez cli refactor * Address fede's review * Remove useless func args * Add back clientCtx to tx command * Update comments * Update docs * Small refactor * remove Init() Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent a417b38 commit f8df05f

File tree

4 files changed

+179
-80
lines changed

4 files changed

+179
-80
lines changed

x/upgrade/client/cli/query.go

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,102 @@
11
package cli
22

33
import (
4-
"encoding/binary"
4+
"context"
55
"fmt"
66

7-
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
8-
97
"github.com/spf13/cobra"
108

119
"github.com/cosmos/cosmos-sdk/client"
12-
"github.com/cosmos/cosmos-sdk/codec"
10+
"github.com/cosmos/cosmos-sdk/client/flags"
11+
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
1312
)
1413

15-
// GetPlanCmd returns the query upgrade plan command
16-
func GetPlanCmd(storeName string, cdc *codec.Codec) *cobra.Command {
14+
// GetQueryCmd returns the parent command for all x/upgrade CLi query commands
15+
func GetQueryCmd() *cobra.Command {
16+
cmd := &cobra.Command{
17+
Use: types.ModuleName,
18+
Short: "Querying commands for the upgrade module",
19+
}
20+
cmd.AddCommand(flags.GetCommands(
21+
GetCurrentPlanCmd(),
22+
GetAppliedPlanCmd(),
23+
)...)
24+
25+
return cmd
26+
}
27+
28+
// GetCurrentPlanCmd returns the query upgrade plan command
29+
func GetCurrentPlanCmd() *cobra.Command {
1730
return &cobra.Command{
1831
Use: "plan",
1932
Short: "get upgrade plan (if one exists)",
2033
Long: "Gets the currently scheduled upgrade plan, if one exists",
2134
Args: cobra.ExactArgs(0),
2235
RunE: func(cmd *cobra.Command, args []string) error {
23-
clientCtx := client.NewContext().WithCodec(cdc).WithJSONMarshaler(cdc)
36+
clientCtx := client.GetClientContextFromCmd(cmd)
37+
queryClient := types.NewQueryClient(clientCtx)
2438

25-
// ignore height for now
26-
res, _, err := clientCtx.Query(fmt.Sprintf("custom/%s/%s", types.QuerierKey, types.QueryCurrent))
39+
params := types.NewQueryCurrentPlanRequest()
40+
res, err := queryClient.CurrentPlan(context.Background(), params)
2741
if err != nil {
2842
return err
2943
}
3044

31-
if len(res) == 0 {
45+
if len(res.Plan.Name) == 0 {
3246
return fmt.Errorf("no upgrade scheduled")
3347
}
3448

35-
var plan types.Plan
36-
err = cdc.UnmarshalJSON(res, &plan)
3749
if err != nil {
3850
return err
3951
}
40-
return clientCtx.PrintOutput(plan)
52+
return clientCtx.PrintOutput(res.Plan)
4153
},
4254
}
4355
}
4456

45-
// GetAppliedHeightCmd returns the height at which a completed upgrade was applied
46-
func GetAppliedHeightCmd(storeName string, cdc *codec.Codec) *cobra.Command {
57+
// GetAppliedPlanCmd returns information about the block at which a completed
58+
// upgrade was applied
59+
func GetAppliedPlanCmd() *cobra.Command {
4760
return &cobra.Command{
4861
Use: "applied [upgrade-name]",
4962
Short: "block header for height at which a completed upgrade was applied",
5063
Long: "If upgrade-name was previously executed on the chain, this returns the header for the block at which it was applied.\n" +
5164
"This helps a client determine which binary was valid over a given range of blocks, as well as more context to understand past migrations.",
5265
Args: cobra.ExactArgs(1),
5366
RunE: func(cmd *cobra.Command, args []string) error {
54-
clientCtx := client.NewContext().WithCodec(cdc).WithJSONMarshaler(cdc)
67+
clientCtx := client.GetClientContextFromCmd(cmd)
68+
queryClient := types.NewQueryClient(clientCtx)
5569

5670
name := args[0]
5771
params := types.NewQueryAppliedPlanRequest(name)
58-
bz, err := clientCtx.JSONMarshaler.MarshalJSON(params)
59-
if err != nil {
60-
return err
61-
}
62-
63-
res, _, err := clientCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierKey, types.QueryApplied), bz)
72+
res, err := queryClient.AppliedPlan(context.Background(), params)
6473
if err != nil {
6574
return err
6675
}
6776

68-
if len(res) == 0 {
77+
if res.Height == 0 {
6978
return fmt.Errorf("no upgrade found")
7079
}
71-
if len(res) != 8 {
72-
return fmt.Errorf("unknown format for applied-upgrade")
73-
}
74-
applied := int64(binary.BigEndian.Uint64(res))
7580

7681
// we got the height, now let's return the headers
7782
node, err := clientCtx.GetNode()
7883
if err != nil {
7984
return err
8085
}
81-
headers, err := node.BlockchainInfo(applied, applied)
86+
headers, err := node.BlockchainInfo(res.Height, res.Height)
8287
if err != nil {
8388
return err
8489
}
8590
if len(headers.BlockMetas) == 0 {
86-
return fmt.Errorf("no headers returned for height %d", applied)
91+
return fmt.Errorf("no headers returned for height %d", res.Height)
8792
}
8893

8994
// always output json as Header is unreable in toml ([]byte is a long list of numbers)
90-
bz, err = cdc.MarshalJSONIndent(headers.BlockMetas[0], "", " ")
95+
bz, err := clientCtx.Codec.MarshalJSONIndent(headers.BlockMetas[0], "", " ")
9196
if err != nil {
9297
return err
9398
}
94-
fmt.Println(string(bz))
95-
return nil
99+
return clientCtx.PrintOutput(string(bz))
96100
},
97101
}
98102
}

x/upgrade/client/cli/tx.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ import (
44
"fmt"
55
"time"
66

7-
"github.com/cosmos/cosmos-sdk/client/tx"
8-
gov "github.com/cosmos/cosmos-sdk/x/gov/types"
9-
10-
"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
11-
127
"github.com/spf13/cobra"
138

149
"github.com/cosmos/cosmos-sdk/client"
10+
"github.com/cosmos/cosmos-sdk/client/flags"
11+
"github.com/cosmos/cosmos-sdk/client/tx"
1512
sdk "github.com/cosmos/cosmos-sdk/types"
13+
"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
14+
gov "github.com/cosmos/cosmos-sdk/x/gov/types"
1615
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
1716
)
1817

@@ -25,9 +24,19 @@ const (
2524
FlagUpgradeInfo = "info"
2625
)
2726

27+
// GetTxCmd returns the transaction commands for this module
28+
func GetTxCmd() *cobra.Command {
29+
cmd := &cobra.Command{
30+
Use: types.ModuleName,
31+
Short: "Upgrade transaction subcommands",
32+
}
33+
cmd.AddCommand(flags.PostCommands()...)
34+
35+
return cmd
36+
}
37+
2838
// NewCmdSubmitUpgradeProposal implements a command handler for submitting a software upgrade proposal transaction.
2939
func NewCmdSubmitUpgradeProposal(clientCtx client.Context) *cobra.Command {
30-
3140
cmd := &cobra.Command{
3241
Use: "software-upgrade [name] (--upgrade-height [height] | --upgrade-time [time]) (--upgrade-info [info]) [flags]",
3342
Args: cobra.ExactArgs(1),

x/upgrade/keeper/grpc_query_test.go

Lines changed: 125 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,143 @@ package keeper_test
22

33
import (
44
gocontext "context"
5+
"fmt"
56
"testing"
67

8+
"github.com/stretchr/testify/suite"
9+
10+
abci "github.com/tendermint/tendermint/abci/types"
11+
712
"github.com/cosmos/cosmos-sdk/baseapp"
813
"github.com/cosmos/cosmos-sdk/simapp"
914
sdk "github.com/cosmos/cosmos-sdk/types"
1015
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
11-
"github.com/stretchr/testify/require"
12-
abci "github.com/tendermint/tendermint/abci/types"
1316
)
1417

15-
func TestGRPCQueryUpgrade(t *testing.T) {
16-
app := simapp.Setup(false)
17-
ctx := app.BaseApp.NewContext(false, abci.Header{})
18+
type UpgradeTestSuite struct {
19+
suite.Suite
20+
21+
app *simapp.SimApp
22+
ctx sdk.Context
23+
queryClient types.QueryClient
24+
}
25+
26+
func (suite *UpgradeTestSuite) SetupTest() {
27+
suite.app = simapp.Setup(false)
28+
suite.ctx = suite.app.BaseApp.NewContext(false, abci.Header{})
29+
30+
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
31+
types.RegisterQueryServer(queryHelper, suite.app.UpgradeKeeper)
32+
suite.queryClient = types.NewQueryClient(queryHelper)
33+
}
34+
35+
func (suite *UpgradeTestSuite) TestQueryCurrentPlan() {
36+
var (
37+
req *types.QueryCurrentPlanRequest
38+
expResponse types.QueryCurrentPlanResponse
39+
)
40+
41+
testCases := []struct {
42+
msg string
43+
malleate func()
44+
expPass bool
45+
}{
46+
{
47+
"without current upgrade plan",
48+
func() {
49+
req = types.NewQueryCurrentPlanRequest()
50+
expResponse = types.QueryCurrentPlanResponse{}
51+
},
52+
true,
53+
},
54+
{
55+
"with current upgrade plan",
56+
func() {
57+
plan := types.Plan{Name: "test-plan", Height: 5}
58+
suite.app.UpgradeKeeper.ScheduleUpgrade(suite.ctx, plan)
1859

19-
queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry())
20-
types.RegisterQueryServer(queryHelper, app.UpgradeKeeper)
21-
queryClient := types.NewQueryClient(queryHelper)
60+
req = types.NewQueryCurrentPlanRequest()
61+
expResponse = types.QueryCurrentPlanResponse{Plan: &plan}
62+
},
63+
true,
64+
},
65+
}
2266

23-
t.Log("Verify that the scheduled upgrade plan can be queried")
24-
plan := types.Plan{Name: "test-plan", Height: 5}
25-
app.UpgradeKeeper.ScheduleUpgrade(ctx, plan)
67+
for _, tc := range testCases {
68+
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
69+
suite.SetupTest() // reset
2670

27-
res, err := queryClient.CurrentPlan(gocontext.Background(), &types.QueryCurrentPlanRequest{})
28-
require.NoError(t, err)
29-
require.Equal(t, res.Plan, &plan)
71+
tc.malleate()
3072

31-
t.Log("Verify that the upgrade plan can be successfully applied and queried")
32-
ctx = ctx.WithBlockHeight(5)
33-
app.UpgradeKeeper.SetUpgradeHandler("test-plan", func(ctx sdk.Context, plan types.Plan) {})
34-
app.UpgradeKeeper.ApplyUpgrade(ctx, plan)
73+
res, err := suite.queryClient.CurrentPlan(gocontext.Background(), req)
3574

36-
res, err = queryClient.CurrentPlan(gocontext.Background(), &types.QueryCurrentPlanRequest{})
37-
require.NoError(t, err)
38-
require.Nil(t, res.Plan)
75+
if tc.expPass {
76+
suite.Require().NoError(err)
77+
suite.Require().NotNil(res)
78+
suite.Require().Equal(&expResponse, res)
79+
} else {
80+
suite.Require().Error(err)
81+
}
82+
})
83+
}
84+
}
85+
86+
func (suite *UpgradeTestSuite) TestAppliedCurrentPlan() {
87+
var (
88+
req *types.QueryAppliedPlanRequest
89+
expHeight int64
90+
)
91+
92+
testCases := []struct {
93+
msg string
94+
malleate func()
95+
expPass bool
96+
}{
97+
{
98+
"with non-existent upgrade plan",
99+
func() {
100+
req = types.NewQueryAppliedPlanRequest("foo")
101+
},
102+
true,
103+
},
104+
{
105+
"with applied upgrade plan",
106+
func() {
107+
expHeight = 5
108+
109+
planName := "test-plan"
110+
plan := types.Plan{Name: planName, Height: expHeight}
111+
suite.app.UpgradeKeeper.ScheduleUpgrade(suite.ctx, plan)
112+
113+
suite.ctx = suite.ctx.WithBlockHeight(expHeight)
114+
suite.app.UpgradeKeeper.SetUpgradeHandler(planName, func(ctx sdk.Context, plan types.Plan) {})
115+
suite.app.UpgradeKeeper.ApplyUpgrade(suite.ctx, plan)
116+
117+
req = types.NewQueryAppliedPlanRequest(planName)
118+
},
119+
true,
120+
},
121+
}
122+
123+
for _, tc := range testCases {
124+
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
125+
suite.SetupTest() // reset
126+
127+
tc.malleate()
128+
129+
res, err := suite.queryClient.AppliedPlan(gocontext.Background(), req)
130+
131+
if tc.expPass {
132+
suite.Require().NoError(err)
133+
suite.Require().NotNil(res)
134+
suite.Require().Equal(expHeight, res.Height)
135+
} else {
136+
suite.Require().Error(err)
137+
}
138+
})
139+
}
140+
}
39141

40-
appliedRes, appliedErr := queryClient.AppliedPlan(gocontext.Background(), &types.QueryAppliedPlanRequest{Name: "test-plan"})
41-
require.NoError(t, appliedErr)
42-
require.Equal(t, int64(5), appliedRes.Height)
142+
func TestUpgradeTestSuite(t *testing.T) {
143+
suite.Run(t, new(UpgradeTestSuite))
43144
}

x/upgrade/module.go

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
abci "github.com/tendermint/tendermint/abci/types"
1212

1313
"github.com/cosmos/cosmos-sdk/client"
14-
"github.com/cosmos/cosmos-sdk/client/flags"
1514
"github.com/cosmos/cosmos-sdk/codec"
1615
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
1716
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -54,27 +53,13 @@ func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, r *mux.Router
5453
}
5554

5655
// GetQueryCmd returns the cli query commands for this module
57-
func (AppModuleBasic) GetQueryCmd(clientCtx client.Context) *cobra.Command {
58-
queryCmd := &cobra.Command{
59-
Use: "upgrade",
60-
Short: "Querying commands for the upgrade module",
61-
}
62-
queryCmd.AddCommand(flags.GetCommands(
63-
cli.GetPlanCmd(types.StoreKey, clientCtx.Codec),
64-
cli.GetAppliedHeightCmd(types.StoreKey, clientCtx.Codec),
65-
)...)
66-
67-
return queryCmd
56+
func (AppModuleBasic) GetQueryCmd(_ client.Context) *cobra.Command {
57+
return cli.GetQueryCmd()
6858
}
6959

7060
// GetTxCmd returns the transaction commands for this module
7161
func (AppModuleBasic) GetTxCmd(_ client.Context) *cobra.Command {
72-
txCmd := &cobra.Command{
73-
Use: "upgrade",
74-
Short: "Upgrade transaction subcommands",
75-
}
76-
txCmd.AddCommand(flags.PostCommands()...)
77-
return txCmd
62+
return cli.GetTxCmd()
7863
}
7964

8065
func (b AppModuleBasic) RegisterInterfaceTypes(registry codectypes.InterfaceRegistry) {

0 commit comments

Comments
 (0)