feat(autocli): add text|json output for flag output (#15252)
This commit is contained in:
parent
fab029bff5
commit
34192a089b
@ -62,6 +62,7 @@ func (appOptions AppOptions) EnhanceRootCommand(rootCmd *cobra.Command) error {
|
||||
return client.GetClientQueryContext(cmd)
|
||||
},
|
||||
AddQueryConnFlags: flags.AddQueryFlagsToCmd,
|
||||
AddTxConnFlags: flags.AddTxFlagsToCmd,
|
||||
}
|
||||
|
||||
return appOptions.EnhanceRootCommandWithBuilder(rootCmd, builder)
|
||||
|
||||
@ -17,4 +17,6 @@ type Builder struct {
|
||||
GetClientConn func(*cobra.Command) (grpc.ClientConnInterface, error)
|
||||
|
||||
AddQueryConnFlags func(*cobra.Command)
|
||||
|
||||
AddTxConnFlags func(*cobra.Command)
|
||||
}
|
||||
|
||||
@ -2,8 +2,11 @@ package autocli
|
||||
|
||||
import (
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
"fmt"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"cosmossdk.io/client/v2/internal/util"
|
||||
)
|
||||
@ -14,10 +17,6 @@ func (b *Builder) buildMethodCommandCommon(descriptor protoreflect.MethodDescrip
|
||||
options = &autocliv1.RpcCommandOptions{}
|
||||
}
|
||||
|
||||
if options.Skip {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
long := options.Long
|
||||
if long == "" {
|
||||
long = util.DescriptorDocs(descriptor)
|
||||
@ -58,10 +57,6 @@ func (b *Builder) buildMethodCommandCommon(descriptor protoreflect.MethodDescrip
|
||||
return exec(cmd, input)
|
||||
}
|
||||
|
||||
if b.AddQueryConnFlags != nil {
|
||||
b.AddQueryConnFlags(cmd)
|
||||
}
|
||||
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
@ -108,3 +103,22 @@ func (b *Builder) enhanceCommandCommon(cmd *cobra.Command, moduleOptions map[str
|
||||
|
||||
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
|
||||
outputType := cmd.Flag(flags.FlagOutput)
|
||||
if outputType == nil {
|
||||
return fmt.Errorf("output flag not found")
|
||||
|
||||
}
|
||||
if outputType.Value.String() == "text" {
|
||||
out, err = yaml.JSONToYAML(out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = fmt.Fprintln(cmd.OutOrStdout(), string(out))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package autocli
|
||||
import (
|
||||
"bytes"
|
||||
"cosmossdk.io/client/v2/internal/testpb"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc"
|
||||
"gotest.tools/v3/assert"
|
||||
@ -43,6 +44,8 @@ func testExecCommon(t *testing.T, buildModuleCommand func(string, *Builder) (*co
|
||||
GetClientConn: func(*cobra.Command) (grpc.ClientConnInterface, error) {
|
||||
return conn, nil
|
||||
},
|
||||
AddQueryConnFlags: flags.AddQueryFlagsToCmd,
|
||||
AddTxConnFlags: flags.AddTxFlagsToCmd,
|
||||
}
|
||||
|
||||
cmd, err := buildModuleCommand("test", b)
|
||||
|
||||
@ -82,7 +82,14 @@ func (b *Builder) AddMsgServiceCommands(cmd *cobra.Command, cmdDescriptor *autoc
|
||||
methodsLength := methods.Len()
|
||||
for i := 0; i < methodsLength; i++ {
|
||||
methodDescriptor := methods.Get(i)
|
||||
methodOpts := rpcOptMap[methodDescriptor.Name()]
|
||||
methodOpts, ok := rpcOptMap[methodDescriptor.Name()]
|
||||
if !ok {
|
||||
methodOpts = &autocliv1.RpcCommandOptions{}
|
||||
}
|
||||
|
||||
if methodOpts.Skip {
|
||||
continue
|
||||
}
|
||||
methodCmd, err := b.BuildMsgMethodCommand(methodDescriptor, methodOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -104,13 +111,17 @@ func (b *Builder) BuildMsgMethodCommand(descriptor protoreflect.MethodDescriptor
|
||||
Resolver: b.TypeResolver,
|
||||
}
|
||||
|
||||
return b.buildMethodCommandCommon(descriptor, options, func(cmd *cobra.Command, input protoreflect.Message) error {
|
||||
cmd, err := b.buildMethodCommandCommon(descriptor, options, func(cmd *cobra.Command, input protoreflect.Message) error {
|
||||
bz, err := jsonMarshalOptions.Marshal(input.Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(cmd.OutOrStdout(), string(bz))
|
||||
err = b.outOrStdoutFormat(cmd, bz)
|
||||
return err
|
||||
})
|
||||
if b.AddTxConnFlags != nil {
|
||||
b.AddTxConnFlags(cmd)
|
||||
}
|
||||
return cmd, err
|
||||
}
|
||||
|
||||
@ -104,6 +104,7 @@ func TestMsgOptions(t *testing.T) {
|
||||
"send", "5", "6", `{"denom":"foo","amount":"1"}`,
|
||||
"--uint32", "7",
|
||||
"--u64", "8",
|
||||
"--output", "json",
|
||||
)
|
||||
response := conn.out.String()
|
||||
var output testpb.MsgRequest
|
||||
@ -114,6 +115,21 @@ func TestMsgOptions(t *testing.T) {
|
||||
assert.Equal(t, output.GetPositional2(), "6")
|
||||
}
|
||||
|
||||
func TestMsgOutputFormat(t *testing.T) {
|
||||
conn := testExecCommon(t, buildModuleMsgCommand,
|
||||
"send", "5", "6", `{"denom":"foo","amount":"1"}`,
|
||||
"--output", "json",
|
||||
)
|
||||
assert.Assert(t, strings.Contains(conn.out.String(), "{"))
|
||||
conn = testExecCommon(t, buildModuleMsgCommand,
|
||||
"send", "5", "6", `{"denom":"foo","amount":"1"}`,
|
||||
"--output", "text",
|
||||
)
|
||||
|
||||
assert.Assert(t, strings.Contains(conn.out.String(), "positional1: 5"))
|
||||
|
||||
}
|
||||
|
||||
func TestMsgOptionsError(t *testing.T) {
|
||||
conn := testExecCommon(t, buildModuleMsgCommand,
|
||||
"send", "5",
|
||||
@ -151,6 +167,7 @@ func TestEverythingMsg(t *testing.T) {
|
||||
"abc",
|
||||
`{"denom":"foo","amount":"1234"}`,
|
||||
`{"denom":"bar","amount":"4321"}`,
|
||||
"--output", "json",
|
||||
"--a-bool",
|
||||
"--an-enum", "two",
|
||||
"--a-message", `{"bar":"abc", "baz":-3}`,
|
||||
|
||||
@ -84,15 +84,22 @@ func (b *Builder) AddQueryServiceCommands(cmd *cobra.Command, cmdDescriptor *aut
|
||||
n := methods.Len()
|
||||
for i := 0; i < n; i++ {
|
||||
methodDescriptor := methods.Get(i)
|
||||
methodOpts := rpcOptMap[methodDescriptor.Name()]
|
||||
methodOpts, ok := rpcOptMap[methodDescriptor.Name()]
|
||||
if !ok {
|
||||
methodOpts = &autocliv1.RpcCommandOptions{}
|
||||
}
|
||||
|
||||
if methodOpts.Skip {
|
||||
continue
|
||||
}
|
||||
|
||||
methodCmd, err := b.BuildQueryMethodCommand(methodDescriptor, methodOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if methodCmd != nil {
|
||||
cmd.AddCommand(methodCmd)
|
||||
}
|
||||
cmd.AddCommand(methodCmd)
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -131,7 +138,7 @@ func (b *Builder) BuildQueryMethodCommand(descriptor protoreflect.MethodDescript
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(cmd.OutOrStdout(), string(bz))
|
||||
err = b.outOrStdoutFormat(cmd, bz)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@ -157,6 +157,23 @@ func TestOptions(t *testing.T) {
|
||||
assert.Equal(t, uint64(5), lastReq.U64) // no opt default value got set
|
||||
}
|
||||
|
||||
func TestOutputFormat(t *testing.T) {
|
||||
conn := testExecCommon(t, buildModuleQueryCommand,
|
||||
"echo",
|
||||
"1", "abc", `{"denom":"foo","amount":"1"}`,
|
||||
"--output", "json",
|
||||
)
|
||||
assert.Assert(t, strings.Contains(conn.out.String(), "{"))
|
||||
conn = testExecCommon(t, buildModuleQueryCommand,
|
||||
"echo",
|
||||
"1", "abc", `{"denom":"foo","amount":"1"}`,
|
||||
"--output", "text",
|
||||
)
|
||||
fmt.Println(conn.out.String())
|
||||
assert.Assert(t, strings.Contains(conn.out.String(), " positional1: 1"))
|
||||
|
||||
}
|
||||
|
||||
func TestHelp(t *testing.T) {
|
||||
conn := testExecCommon(t, buildModuleQueryCommand, "-h")
|
||||
golden.Assert(t, conn.out.String(), "help-toplevel.golden")
|
||||
|
||||
@ -8,18 +8,38 @@ Flags:
|
||||
--a-bool
|
||||
--a-coin cosmos.base.v1beta1.Coin (json)
|
||||
--a-message testpb.AMessage (json)
|
||||
-a, --account-number uint The account number of the signing account (offline mode only)
|
||||
--an-address bech32 account address key name
|
||||
--an-enum Enum (unspecified | one | two | five | neg-three) (default unspecified)
|
||||
--aux Generate aux signer data instead of sending a tx
|
||||
--bools bools (default [])
|
||||
-b, --broadcast-mode string Transaction broadcasting mode (sync|async) (default "sync")
|
||||
--bz bytesBase64
|
||||
--chain-id string The network chain ID
|
||||
--deprecated-field string
|
||||
--dry-run ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it (when enabled, the local Keybase is not accessible)
|
||||
--duration duration
|
||||
--durations duration (repeated)
|
||||
--enums Enum (unspecified | one | two | five | neg-three) (repeated)
|
||||
--fee-granter string Fee granter grants fees for the transaction
|
||||
--fee-payer string Fee payer pays fees for the transaction instead of deducting from the signer
|
||||
--fees string Fees to pay along with transaction; eg: 10uatom
|
||||
--from string Name or address of private key with which to sign
|
||||
--gas string gas limit to set per-transaction; set to "auto" to calculate sufficient gas automatically. Note: "auto" option doesn't always report accurate results. Set a valid coin value to adjust the result. Can be used instead of "fees". (default 200000)
|
||||
--gas-adjustment float adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored (default 1)
|
||||
--gas-prices string Gas prices in decimal format to determine the transaction fee (e.g. 0.1uatom)
|
||||
--generate-only Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase only accessed when providing a key name)
|
||||
-h, --help help for send
|
||||
--hidden-bool
|
||||
--i32 int32
|
||||
--i64 int
|
||||
--keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "os")
|
||||
--keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used
|
||||
--ledger Use a connected Ledger device
|
||||
--node string <host>:<port> to CometBFT rpc interface for this chain (default "tcp://localhost:26657")
|
||||
--note string Note to add a description to the transaction (previously --memo)
|
||||
--offline Offline mode (does not allow any online functionality)
|
||||
-o, --output string Output format (text|json) (default "json")
|
||||
--page-count-total
|
||||
--page-key bytesBase64
|
||||
--page-limit uint
|
||||
@ -28,11 +48,16 @@ Flags:
|
||||
--positional1 int32
|
||||
--positional2 string
|
||||
--positional3-varargs cosmos.base.v1beta1.Coin (json) (repeated)
|
||||
-s, --sequence uint The sequence number of the signing account (offline mode only)
|
||||
--shorthand-deprecated-field string
|
||||
--sign-mode string Choose sign mode (direct|amino-json|direct-aux), this is an advanced feature
|
||||
--some-messages testpb.AMessage (json) (repeated)
|
||||
--str string
|
||||
--strings strings
|
||||
--timeout-height uint Set a block timeout height to prevent the tx from being committed past a certain height
|
||||
--timestamp timestamp (RFC 3339)
|
||||
--tip string Tip is the amount that is going to be transferred to the fee payer on the target chain. This flag is only valid when used with --aux, and is ignored if the target chain didn't enable the TipDecorator
|
||||
--u32 uint32
|
||||
--u64 uint
|
||||
--uints uints (default [])
|
||||
-y, --yes Skip tx broadcasting prompt confirmation
|
||||
|
||||
@ -14,10 +14,15 @@ Flags:
|
||||
--duration duration
|
||||
--durations duration (repeated)
|
||||
--enums Enum (unspecified | one | two | five | neg-three) (repeated)
|
||||
--grpc-addr string the gRPC endpoint to use for this chain
|
||||
--grpc-insecure allow gRPC over insecure channels, if not the server must use TLS
|
||||
--height int Use a specific height to query state at (this can error if the node is pruning state)
|
||||
-h, --help help for echo
|
||||
--hidden-bool
|
||||
--i32 int32
|
||||
--i64 int
|
||||
--node string <host>:<port> to CometBFT RPC interface for this chain (default "tcp://localhost:26657")
|
||||
-o, --output string Output format (text|json) (default "text")
|
||||
--page-count-total
|
||||
--page-key bytesBase64
|
||||
--page-limit uint
|
||||
|
||||
25
client/v2/autocli/testdata/help-echo-msg.golden
vendored
25
client/v2/autocli/testdata/help-echo-msg.golden
vendored
@ -13,28 +13,53 @@ Flags:
|
||||
--a-bool
|
||||
--a-coin cosmos.base.v1beta1.Coin (json)
|
||||
--a-message testpb.AMessage (json)
|
||||
-a, --account-number uint The account number of the signing account (offline mode only)
|
||||
--an-address bech32 account address key name
|
||||
--an-enum Enum (unspecified | one | two | five | neg-three) (default unspecified)
|
||||
--aux Generate aux signer data instead of sending a tx
|
||||
--bools bools (default [])
|
||||
-b, --broadcast-mode string Transaction broadcasting mode (sync|async) (default "sync")
|
||||
--bz bytesBase64
|
||||
--chain-id string The network chain ID
|
||||
--deprecated-field string (DEPRECATED: don't use this)
|
||||
--dry-run ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it (when enabled, the local Keybase is not accessible)
|
||||
--duration duration
|
||||
--durations duration (repeated)
|
||||
--enums Enum (unspecified | one | two | five | neg-three) (repeated)
|
||||
--fee-granter string Fee granter grants fees for the transaction
|
||||
--fee-payer string Fee payer pays fees for the transaction instead of deducting from the signer
|
||||
--fees string Fees to pay along with transaction; eg: 10uatom
|
||||
--from string Name or address of private key with which to sign
|
||||
--gas string gas limit to set per-transaction; set to "auto" to calculate sufficient gas automatically. Note: "auto" option doesn't always report accurate results. Set a valid coin value to adjust the result. Can be used instead of "fees". (default 200000)
|
||||
--gas-adjustment float adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored (default 1)
|
||||
--gas-prices string Gas prices in decimal format to determine the transaction fee (e.g. 0.1uatom)
|
||||
--generate-only Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase only accessed when providing a key name)
|
||||
-h, --help help for send
|
||||
--i32 int32 some random int32
|
||||
--i64 int
|
||||
--keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "os")
|
||||
--keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used
|
||||
--ledger Use a connected Ledger device
|
||||
--node string <host>:<port> to CometBFT rpc interface for this chain (default "tcp://localhost:26657")
|
||||
--note string Note to add a description to the transaction (previously --memo)
|
||||
--offline Offline mode (does not allow any online functionality)
|
||||
-o, --output string Output format (text|json) (default "json")
|
||||
--page-count-total
|
||||
--page-key bytesBase64
|
||||
--page-limit uint
|
||||
--page-offset uint
|
||||
--page-reverse
|
||||
-s, --sequence uint The sequence number of the signing account (offline mode only)
|
||||
-d, --shorthand-deprecated-field string (DEPRECATED: bad idea)
|
||||
--sign-mode string Choose sign mode (direct|amino-json|direct-aux), this is an advanced feature
|
||||
--some-messages testpb.AMessage (json) (repeated)
|
||||
--str string
|
||||
--strings strings
|
||||
--timeout-height uint Set a block timeout height to prevent the tx from being committed past a certain height
|
||||
--timestamp timestamp (RFC 3339)
|
||||
--tip string Tip is the amount that is going to be transferred to the fee payer on the target chain. This flag is only valid when used with --aux, and is ignored if the target chain didn't enable the TipDecorator
|
||||
--u64 uint some random uint64
|
||||
-u, --uint32 uint32 some random uint32
|
||||
--uints uints (default [])
|
||||
-v, --version version for send
|
||||
-y, --yes Skip tx broadcasting prompt confirmation
|
||||
|
||||
5
client/v2/autocli/testdata/help-echo.golden
vendored
5
client/v2/autocli/testdata/help-echo.golden
vendored
@ -21,9 +21,14 @@ Flags:
|
||||
--duration duration
|
||||
--durations duration (repeated)
|
||||
--enums Enum (unspecified | one | two | five | neg-three) (repeated)
|
||||
--grpc-addr string the gRPC endpoint to use for this chain
|
||||
--grpc-insecure allow gRPC over insecure channels, if not the server must use TLS
|
||||
--height int Use a specific height to query state at (this can error if the node is pruning state)
|
||||
-h, --help help for echo
|
||||
--i32 int32 some random int32
|
||||
--i64 int
|
||||
--node string <host>:<port> to CometBFT RPC interface for this chain (default "tcp://localhost:26657")
|
||||
-o, --output string Output format (text|json) (default "text")
|
||||
--page-count-total
|
||||
--page-key bytesBase64
|
||||
--page-limit uint
|
||||
|
||||
Loading…
Reference in New Issue
Block a user