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

feat(client/v2): combine autocli and custom cmd within a module #17088

Merged
merged 7 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions client/v2/autocli/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ func (appOptions AppOptions) EnhanceRootCommandWithBuilder(rootCmd *cobra.Comman
}

if queryCmd := findSubCommand(rootCmd, "query"); queryCmd != nil {
if err := builder.enhanceCommandCommon(queryCmd, appOptions, customQueryCmds, enhanceQuery); err != nil {
if err := builder.enhanceCommandCommon(queryCmd, queryCmdType, appOptions, customQueryCmds); err != nil {
return err
}
} else {
queryCmd, err := builder.BuildQueryCommand(appOptions, customQueryCmds, enhanceQuery)
queryCmd, err := builder.BuildQueryCommand(appOptions, customQueryCmds)
if err != nil {
return err
}
Expand All @@ -115,11 +115,11 @@ func (appOptions AppOptions) EnhanceRootCommandWithBuilder(rootCmd *cobra.Comman
}

if msgCmd := findSubCommand(rootCmd, "tx"); msgCmd != nil {
if err := builder.enhanceCommandCommon(msgCmd, appOptions, customMsgCmds, enhanceMsg); err != nil {
if err := builder.enhanceCommandCommon(msgCmd, msgCmdType, appOptions, customMsgCmds); err != nil {
return err
}
} else {
subCmd, err := builder.BuildMsgCommand(appOptions, customMsgCmds, enhanceMsg)
subCmd, err := builder.BuildMsgCommand(appOptions, customMsgCmds)
if err != nil {
return err
}
Expand Down
72 changes: 57 additions & 15 deletions client/v2/autocli/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
)

type cmdType int

const (
queryCmdType cmdType = iota
msgCmdType
)

func (b *Builder) buildMethodCommandCommon(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions, exec func(cmd *cobra.Command, input protoreflect.Message) error) (*cobra.Command, error) {
if options == nil {
// use the defaults
Expand Down Expand Up @@ -73,9 +80,9 @@ func (b *Builder) buildMethodCommandCommon(descriptor protoreflect.MethodDescrip
// automatically fill in missing commands.
func (b *Builder) enhanceCommandCommon(
cmd *cobra.Command,
cmdType cmdType,
appOptions AppOptions,
customCmds map[string]*cobra.Command,
buildModuleCommand enhanceCommandFunc,
) error {
moduleOptions := appOptions.ModuleOptions
if len(moduleOptions) == 0 {
Expand All @@ -89,38 +96,54 @@ func (b *Builder) enhanceCommandCommon(

modules := append(maps.Keys(appOptions.Modules), maps.Keys(moduleOptions)...)
for _, moduleName := range modules {
modOpts, hasModuleOptions := moduleOptions[moduleName]

// if we have an existing command skip adding one here
if findSubCommand(cmd, moduleName) != nil {
if subCmd := findSubCommand(cmd, moduleName); subCmd != nil {
if hasModuleOptions {
if err := enhanceCustomCmd(b, subCmd, cmdType, modOpts); err != nil {
return err
}
}

continue
}

// if we have a custom command use that instead of generating one
if custom := customCmds[moduleName]; custom != nil {
// custom commands get added lower down
if custom, ok := customCmds[moduleName]; ok {
if hasModuleOptions {
if err := enhanceCustomCmd(b, custom, cmdType, modOpts); err != nil {
return err
}
}

cmd.AddCommand(custom)
continue
}

// check for autocli options
modOpts := moduleOptions[moduleName]
if modOpts == nil {
// if we don't have module options, skip adding a command as we don't have anything to add
if !hasModuleOptions {
continue
}

if err := buildModuleCommand(b, moduleName, cmd, modOpts); err != nil {
return err
switch cmdType {
case queryCmdType:
if err := enhanceQuery(b, moduleName, cmd, modOpts); err != nil {
return err
}
case msgCmdType:
if err := enhanceMsg(b, moduleName, cmd, modOpts); err != nil {
return err
}
}
}

return nil
}

type enhanceCommandFunc func(builder *Builder, moduleName string, cmd *cobra.Command, modOpts *autocliv1.ModuleOptions) error

// enhanceQuery enhances the provided query command with the autocli commands for a module.
func enhanceQuery(builder *Builder, moduleName string, cmd *cobra.Command, modOpts *autocliv1.ModuleOptions) error {
queryCmdDesc := modOpts.Query
if queryCmdDesc != nil {
if queryCmdDesc := modOpts.Query; queryCmdDesc != nil {
subCmd := topLevelCmd(moduleName, fmt.Sprintf("Querying commands for the %s module", moduleName))
if err := builder.AddQueryServiceCommands(subCmd, queryCmdDesc); err != nil {
return err
Expand All @@ -134,8 +157,7 @@ func enhanceQuery(builder *Builder, moduleName string, cmd *cobra.Command, modOp

// enhanceMsg enhances the provided msg command with the autocli commands for a module.
func enhanceMsg(builder *Builder, moduleName string, cmd *cobra.Command, modOpts *autocliv1.ModuleOptions) error {
txCmdDesc := modOpts.Tx
if txCmdDesc != nil {
if txCmdDesc := modOpts.Tx; txCmdDesc != nil {
subCmd := topLevelCmd(moduleName, fmt.Sprintf("Transactions commands for the %s module", moduleName))
if err := builder.AddMsgServiceCommands(subCmd, txCmdDesc); err != nil {
return err
Expand All @@ -147,6 +169,26 @@ func enhanceMsg(builder *Builder, moduleName string, cmd *cobra.Command, modOpts
return nil
}

// enhanceCustomCmd enhances the provided custom query or msg command autocli commands for a module.
func enhanceCustomCmd(builder *Builder, cmd *cobra.Command, cmdType cmdType, modOpts *autocliv1.ModuleOptions) error {
switch cmdType {
case queryCmdType:
if modOpts.Query != nil && modOpts.Query.EnhanceCustomCommand {
if err := builder.AddQueryServiceCommands(cmd, modOpts.Query); err != nil {
return err
}
}
case msgCmdType:
if modOpts.Tx != nil && modOpts.Tx.EnhanceCustomCommand {
if err := builder.AddMsgServiceCommands(cmd, modOpts.Tx); err != nil {
return err
}
}
}

return nil
}

// outOrStdoutFormat formats the output based on the output flag and writes it to the command's output stream.
func (b *Builder) outOrStdoutFormat(cmd *cobra.Command, out []byte) error {
var err error
Expand Down
10 changes: 8 additions & 2 deletions client/v2/autocli/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (
// BuildMsgCommand builds the msg commands for all the provided modules. If a custom command is provided for a
// module, this is used instead of any automatically generated CLI commands. This allows apps to a fully dynamic client
// with a more customized experience if a binary with custom commands is downloaded.
func (b *Builder) BuildMsgCommand(appOptions AppOptions, customCmds map[string]*cobra.Command, buildModuleCommand enhanceCommandFunc) (*cobra.Command, error) {
func (b *Builder) BuildMsgCommand(appOptions AppOptions, customCmds map[string]*cobra.Command) (*cobra.Command, error) {
msgCmd := topLevelCmd("tx", "Transaction subcommands")
if err := b.enhanceCommandCommon(msgCmd, appOptions, customCmds, enhanceMsg); err != nil {
if err := b.enhanceCommandCommon(msgCmd, msgCmdType, appOptions, customCmds); err != nil {
return nil, err
}

Expand Down Expand Up @@ -75,6 +75,12 @@ func (b *Builder) AddMsgServiceCommands(cmd *cobra.Command, cmdDescriptor *autoc
return err
}

if findSubCommand(cmd, methodCmd.Name()) != nil {
// do not overwrite existing commands
// @julienrbrt: should we display a warning?
continue
}

if methodCmd != nil {
cmd.AddCommand(methodCmd)
}
Expand Down
13 changes: 6 additions & 7 deletions client/v2/autocli/msg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (

var buildModuleMsgCommand = func(moduleName string, b *Builder) (*cobra.Command, error) {
cmd := topLevelCmd(moduleName, fmt.Sprintf("Transactions commands for the %s module", moduleName))

err := b.AddMsgServiceCommands(cmd, testCmdMsgDesc)
return cmd, err
}
Expand Down Expand Up @@ -258,7 +257,7 @@ func TestBuildMsgCommand(t *testing.T) {
"test": {Use: "test", Run: func(cmd *cobra.Command, args []string) {
customCommandCalled = true
}},
}, enhanceMsg)
})
assert.NilError(t, err)
cmd.SetArgs([]string{"test", "tx"})
assert.NilError(t, cmd.Execute())
Expand Down Expand Up @@ -295,12 +294,12 @@ func TestErrorBuildMsgCommand(t *testing.T) {
ValidatorAddressCodec: b.ValidatorAddressCodec,
}

_, err := b.BuildMsgCommand(appOptions, nil, enhanceMsg)
_, err := b.BuildMsgCommand(appOptions, nil)
assert.ErrorContains(t, err, "can't find field un-existent-proto-field")

nonExistentService := &autocliv1.ServiceCommandDescriptor{Service: "un-existent-service"}
appOptions.ModuleOptions["test"].Tx = nonExistentService
_, err = b.BuildMsgCommand(appOptions, nil, enhanceMsg)
_, err = b.BuildMsgCommand(appOptions, nil)
assert.ErrorContains(t, err, "can't find service un-existent-service")
}

Expand Down Expand Up @@ -368,7 +367,7 @@ func TestEnhanceMessageCommand(t *testing.T) {
},
}

err := b.enhanceCommandCommon(cmd, appOptions, map[string]*cobra.Command{}, enhanceMsg)
err := b.enhanceCommandCommon(cmd, msgCmdType, appOptions, map[string]*cobra.Command{})
assert.NilError(t, err)

cmd = &cobra.Command{Use: "test"}
Expand All @@ -377,7 +376,7 @@ func TestEnhanceMessageCommand(t *testing.T) {
customCommands := map[string]*cobra.Command{
"test2": {Use: "test"},
}
err = b.enhanceCommandCommon(cmd, appOptions, customCommands, enhanceMsg)
err = b.enhanceCommandCommon(cmd, msgCmdType, appOptions, customCommands)
assert.NilError(t, err)

cmd = &cobra.Command{Use: "test"}
Expand All @@ -387,6 +386,6 @@ func TestEnhanceMessageCommand(t *testing.T) {
},
}
customCommands = map[string]*cobra.Command{}
err = b.enhanceCommandCommon(cmd, appOptions, customCommands, enhanceMsg)
err = b.enhanceCommandCommon(cmd, msgCmdType, appOptions, customCommands)
assert.NilError(t, err)
}
10 changes: 8 additions & 2 deletions client/v2/autocli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import (
// BuildQueryCommand builds the query commands for all the provided modules. If a custom command is provided for a
// module, this is used instead of any automatically generated CLI commands. This allows apps to a fully dynamic client
// with a more customized experience if a binary with custom commands is downloaded.
func (b *Builder) BuildQueryCommand(appOptions AppOptions, customCmds map[string]*cobra.Command, enhanceQuery enhanceCommandFunc) (*cobra.Command, error) {
func (b *Builder) BuildQueryCommand(appOptions AppOptions, customCmds map[string]*cobra.Command) (*cobra.Command, error) {
queryCmd := topLevelCmd("query", "Querying subcommands")
queryCmd.Aliases = []string{"q"}

if err := b.enhanceCommandCommon(queryCmd, appOptions, customCmds, enhanceQuery); err != nil {
if err := b.enhanceCommandCommon(queryCmd, queryCmdType, appOptions, customCmds); err != nil {
return nil, err
}

Expand Down Expand Up @@ -80,6 +80,12 @@ func (b *Builder) AddQueryServiceCommands(cmd *cobra.Command, cmdDescriptor *aut
return err
}

if findSubCommand(cmd, methodCmd.Name()) != nil {
// do not overwrite existing commands
// @julienrbrt: should we display a warning?
continue
}

cmd.AddCommand(methodCmd)
}

Expand Down
3 changes: 1 addition & 2 deletions client/v2/autocli/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ func TestBuildCustomQueryCommand(t *testing.T) {
"test": {Use: "test", Run: func(cmd *cobra.Command, args []string) {
customCommandCalled = true
}},
}, enhanceQuery)
})
assert.NilError(t, err)
cmd.SetArgs([]string{"test", "query"})
assert.NilError(t, cmd.Execute())
Expand All @@ -591,7 +591,6 @@ func TestNotFoundErrors(t *testing.T) {

buildModuleQueryCommand := func(moduleName string, cmdDescriptor *autocliv1.ServiceCommandDescriptor) (*cobra.Command, error) {
cmd := topLevelCmd("query", "Querying subcommands")

err := b.AddMsgServiceCommands(cmd, cmdDescriptor)
return cmd, err
}
Expand Down
Loading