feat: add basic autocli config to every module (#13786)
* feat: add autocli configs to every module * auto-discover config * tests + gov, auth config tweaks * docs * Update x/auth/autocli.go Co-authored-by: Julien Robert <julien@rbrt.fr> * Update x/auth/autocli.go Co-authored-by: Julien Robert <julien@rbrt.fr> * cleanup Co-authored-by: Julien Robert <julien@rbrt.fr> Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com>
This commit is contained in:
parent
4f7d9ea233
commit
bcdf81cbaf
@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
gogogrpc "github.com/cosmos/gogoproto/grpc"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
)
|
||||
@ -22,6 +24,31 @@ func NewAutoCLIQueryService(appModules map[string]module.AppModule) *AutoCLIQuer
|
||||
AutoCLIOptions() *autocliv1.ModuleOptions
|
||||
}); ok {
|
||||
moduleOptions[modName] = autoCliMod.AutoCLIOptions()
|
||||
} else {
|
||||
// try to auto-discover options based on the last msg and query
|
||||
// services registered for the module
|
||||
cfg := &autocliConfigurator{}
|
||||
mod.RegisterServices(cfg)
|
||||
modOptions := &autocliv1.ModuleOptions{}
|
||||
haveServices := false
|
||||
|
||||
if cfg.msgServer.serviceName != "" {
|
||||
haveServices = true
|
||||
modOptions.Tx = &autocliv1.ServiceCommandDescriptor{
|
||||
Service: cfg.msgServer.serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.queryServer.serviceName != "" {
|
||||
haveServices = true
|
||||
modOptions.Query = &autocliv1.ServiceCommandDescriptor{
|
||||
Service: cfg.queryServer.serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
if haveServices {
|
||||
moduleOptions[modName] = modOptions
|
||||
}
|
||||
}
|
||||
}
|
||||
return &AutoCLIQueryService{
|
||||
@ -35,4 +62,27 @@ func (a AutoCLIQueryService) AppOptions(context.Context, *autocliv1.AppOptionsRe
|
||||
}, nil
|
||||
}
|
||||
|
||||
// autocliConfigurator allows us to call RegisterServices and introspect the services
|
||||
type autocliConfigurator struct {
|
||||
msgServer autocliServiceRegistrar
|
||||
queryServer autocliServiceRegistrar
|
||||
}
|
||||
|
||||
func (a *autocliConfigurator) MsgServer() gogogrpc.Server { return &a.msgServer }
|
||||
|
||||
func (a *autocliConfigurator) QueryServer() gogogrpc.Server { return &a.queryServer }
|
||||
|
||||
func (a *autocliConfigurator) RegisterMigration(string, uint64, module.MigrationHandler) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// autocliServiceRegistrar is used to capture the service name for registered services
|
||||
type autocliServiceRegistrar struct {
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func (a *autocliServiceRegistrar) RegisterService(sd *grpc.ServiceDesc, _ interface{}) {
|
||||
a.serviceName = sd.ServiceName
|
||||
}
|
||||
|
||||
var _ autocliv1.QueryServer = &AutoCLIQueryService{}
|
||||
|
||||
@ -127,8 +127,21 @@ func TestQueryAutoCLIAppOptions(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, res != nil && res.ModuleOptions != nil)
|
||||
|
||||
// make sure we at least have x/auth autocli options
|
||||
// make sure we have x/auth autocli options which were configured manually
|
||||
authOpts := res.ModuleOptions["auth"]
|
||||
assert.Assert(t, authOpts != nil)
|
||||
assert.Assert(t, authOpts.Query != nil && authOpts.Query.Service != "")
|
||||
assert.Assert(t, authOpts.Query != nil)
|
||||
assert.Equal(t, "cosmos.auth.v1beta1.Query", authOpts.Query.Service)
|
||||
// make sure we have some custom options
|
||||
assert.Assert(t, len(authOpts.Query.RpcCommandOptions) != 0)
|
||||
|
||||
// make sure we have x/staking autocli options which should have been auto-discovered
|
||||
stakingOpts := res.ModuleOptions["staking"]
|
||||
assert.Assert(t, stakingOpts != nil)
|
||||
assert.Assert(t, stakingOpts.Query != nil && stakingOpts.Tx != nil)
|
||||
assert.Equal(t, "cosmos.staking.v1beta1.Query", stakingOpts.Query.Service)
|
||||
assert.Equal(t, "cosmos.staking.v1beta1.Msg", stakingOpts.Tx.Service)
|
||||
|
||||
// make sure tx module has no autocli options because it has no services
|
||||
assert.Assert(t, res.ModuleOptions["tx"] == nil)
|
||||
}
|
||||
|
||||
32
x/auth/autocli.go
Normal file
32
x/auth/autocli.go
Normal file
@ -0,0 +1,32 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
authv1beta1 "cosmossdk.io/api/cosmos/auth/v1beta1"
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
)
|
||||
|
||||
// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
|
||||
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
|
||||
return &autocliv1.ModuleOptions{
|
||||
Query: &autocliv1.ServiceCommandDescriptor{
|
||||
Service: authv1beta1.Query_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "Account",
|
||||
Use: "account [address]",
|
||||
Short: "query account by address",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}},
|
||||
},
|
||||
{
|
||||
RpcMethod: "AccountAddressByID",
|
||||
Use: "address-by-id [acc-num]",
|
||||
Short: "query account address by account number",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "id"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
Tx: &autocliv1.ServiceCommandDescriptor{
|
||||
Service: authv1beta1.Msg_ServiceDesc.ServiceName,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,6 @@ import (
|
||||
|
||||
"cosmossdk.io/depinject"
|
||||
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
|
||||
modulev1 "cosmossdk.io/api/cosmos/auth/module/v1"
|
||||
@ -111,11 +110,6 @@ func (am AppModule) IsOnePerModuleType() {}
|
||||
// IsAppModule implements the appmodule.AppModule interface.
|
||||
func (am AppModule) IsAppModule() {}
|
||||
|
||||
// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
|
||||
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
|
||||
return types.AutoCLIOptions
|
||||
}
|
||||
|
||||
// NewAppModule creates a new AppModule object
|
||||
func NewAppModule(cdc codec.Codec, accountKeeper keeper.AccountKeeper, randGenAccountsFn types.RandomGenesisAccountsFn, ss exported.Subspace) AppModule {
|
||||
return AppModule{
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
package types
|
||||
|
||||
import autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
|
||||
var AutoCLIOptions = &autocliv1.ModuleOptions{
|
||||
Query: &autocliv1.ServiceCommandDescriptor{
|
||||
Service: _Query_serviceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "Account",
|
||||
Use: "account [address]",
|
||||
Short: "query account by address",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}},
|
||||
},
|
||||
{
|
||||
RpcMethod: "AccountAddressByID",
|
||||
Use: "address-by-id [id]",
|
||||
Short: "query account address by account ID",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "id"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
Tx: &autocliv1.ServiceCommandDescriptor{
|
||||
Service: _Msg_serviceDesc.ServiceName,
|
||||
},
|
||||
}
|
||||
27
x/gov/autocli.go
Normal file
27
x/gov/autocli.go
Normal file
@ -0,0 +1,27 @@
|
||||
package gov
|
||||
|
||||
import (
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
govv1 "cosmossdk.io/api/cosmos/gov/v1"
|
||||
govv1beta1 "cosmossdk.io/api/cosmos/gov/v1beta1"
|
||||
)
|
||||
|
||||
// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
|
||||
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
|
||||
return &autocliv1.ModuleOptions{
|
||||
Tx: &autocliv1.ServiceCommandDescriptor{
|
||||
Service: govv1.Msg_ServiceDesc.ServiceName,
|
||||
// map v1beta1 as a sub-command
|
||||
SubCommands: map[string]*autocliv1.ServiceCommandDescriptor{
|
||||
"v1beta1": {Service: govv1beta1.Msg_ServiceDesc.ServiceName},
|
||||
},
|
||||
},
|
||||
Query: &autocliv1.ServiceCommandDescriptor{
|
||||
Service: govv1.Query_ServiceDesc.ServiceName,
|
||||
// map v1beta1 as a sub-command
|
||||
SubCommands: map[string]*autocliv1.ServiceCommandDescriptor{
|
||||
"v1beta1": {Service: govv1beta1.Query_ServiceDesc.ServiceName},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,7 @@ import (
|
||||
modulev1 "cosmossdk.io/api/cosmos/gov/module/v1"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/depinject"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
@ -121,6 +122,12 @@ func (a AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry
|
||||
v1beta1.RegisterInterfaces(registry)
|
||||
}
|
||||
|
||||
// IsOnePerModuleType implements the depinject.OnePerModuleType interface.
|
||||
func (am AppModule) IsOnePerModuleType() {}
|
||||
|
||||
// IsAppModule implements the appmodule.AppModule interface.
|
||||
func (am AppModule) IsAppModule() {}
|
||||
|
||||
// AppModule implements an application module for the gov module.
|
||||
type AppModule struct {
|
||||
AppModuleBasic
|
||||
|
||||
Loading…
Reference in New Issue
Block a user