From 2ec4a3c8979d9132edc1a979956fa32f2b3000c3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 24 Jan 2022 15:22:47 +0300 Subject: [PATCH] [#1086] neofs-cli: add command for shard dump Signed-off-by: Evgenii Stratonikov --- cmd/neofs-cli/modules/control.go | 2 + cmd/neofs-cli/modules/dump.go | 76 ++++++++++++++++++++++++++++++++ pkg/services/control/rpc.go | 2 +- 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 cmd/neofs-cli/modules/dump.go diff --git a/cmd/neofs-cli/modules/control.go b/cmd/neofs-cli/modules/control.go index 65d9af50..fb521f25 100644 --- a/cmd/neofs-cli/modules/control.go +++ b/cmd/neofs-cli/modules/control.go @@ -181,6 +181,7 @@ func init() { shardsCmd.AddCommand(listShardsCmd) shardsCmd.AddCommand(setShardModeCmd) + shardsCmd.AddCommand(dumpShardCmd) controlCmd.AddCommand( healthCheckCmd, @@ -196,6 +197,7 @@ func init() { initControlSnapshotCmd() initControlShardsListCmd() initControlSetShardModeCmd() + initControlDumpShardCmd() } func healthCheck(cmd *cobra.Command, _ []string) { diff --git a/cmd/neofs-cli/modules/dump.go b/cmd/neofs-cli/modules/dump.go new file mode 100644 index 00000000..9739c9b7 --- /dev/null +++ b/cmd/neofs-cli/modules/dump.go @@ -0,0 +1,76 @@ +package cmd + +import ( + "github.com/mr-tron/base58" + "github.com/nspcc-dev/neofs-node/pkg/services/control" + controlSvc "github.com/nspcc-dev/neofs-node/pkg/services/control/server" + "github.com/nspcc-dev/neofs-sdk-go/util/signature" + "github.com/spf13/cobra" +) + +const ( + dumpFilepathFlag = "path" + dumpIgnoreErrorsFlag = "no-errors" +) + +var dumpShardCmd = &cobra.Command{ + Use: "dump", + Short: "Dump objects from shard", + Long: "Dump objects from shard to a file", + Run: dumpShard, +} + +func dumpShard(cmd *cobra.Command, _ []string) { + key, err := getKeyNoGenerate() + exitOnErr(cmd, err) + + body := new(control.DumpShardRequest_Body) + + rawID, err := base58.Decode(shardID) + exitOnErr(cmd, errf("incorrect shard ID encoding: %w", err)) + body.SetShardID(rawID) + + p, _ := cmd.Flags().GetString(dumpFilepathFlag) + body.SetFilepath(p) + + ignore, _ := cmd.Flags().GetBool(dumpIgnoreErrorsFlag) + body.SetIgnoreErrors(ignore) + + req := new(control.DumpShardRequest) + req.SetBody(body) + + err = controlSvc.SignMessage(key, req) + exitOnErr(cmd, errf("could not sign request: %w", err)) + + cli, err := getControlSDKClient(key) + exitOnErr(cmd, err) + + resp, err := control.DumpShard(cli.Raw(), req) + exitOnErr(cmd, errf("rpc error: %w", err)) + + sign := resp.GetSignature() + + err = signature.VerifyDataWithSource( + resp, + func() ([]byte, []byte) { + return sign.GetKey(), sign.GetSign() + }, + ) + exitOnErr(cmd, errf("invalid response signature: %w", err)) + + cmd.Println("Shard has been dumped successfully.") +} + +func initControlDumpShardCmd() { + initCommonFlagsWithoutRPC(dumpShardCmd) + + flags := dumpShardCmd.Flags() + flags.String(controlRPC, controlRPCDefault, controlRPCUsage) + flags.StringVarP(&shardID, shardIDFlag, "", "", "Shard ID in base58 encoding") + flags.String(dumpFilepathFlag, "", "File to write objects to") + flags.Bool(dumpIgnoreErrorsFlag, false, "Skip invalid/unreadable objects") + + _ = dumpShardCmd.MarkFlagRequired(shardIDFlag) + _ = dumpShardCmd.MarkFlagRequired(dumpFilepathFlag) + _ = dumpShardCmd.MarkFlagRequired(controlRPC) +} diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index 46fba470..eb86a36f 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -148,7 +148,7 @@ func SetShardMode( // DumpShard executes ControlService.DumpShard RPC. func DumpShard(cli *client.Client, req *DumpShardRequest, opts ...client.CallOption) (*DumpShardResponse, error) { - wResp := new(dumpShardResponseWrapper) + wResp := &dumpShardResponseWrapper{new(DumpShardResponse)} wReq := &requestWrapper{m: req} err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcDumpShard), wReq, wResp, opts...)