diff --git a/CHANGELOG.md b/CHANGELOG.md index 77416986d8..ca5130c251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Changelog for NeoFS Node - Indexes inspection command to neofs-lens (#2882) - Add objects sanity checker to neofs-lens (#2506) - Support for 0.20.0+ neofs-contract archive format (#2872) +- `neofs-cli control object status` command (#2886) ### Fixed - Control service's Drop call does not clean metabase (#2822) diff --git a/cmd/neofs-cli/modules/control/objects.go b/cmd/neofs-cli/modules/control/objects.go new file mode 100644 index 0000000000..20ff870e14 --- /dev/null +++ b/cmd/neofs-cli/modules/control/objects.go @@ -0,0 +1,92 @@ +package control + +import ( + "fmt" + + rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" + "github.com/nspcc-dev/neofs-node/pkg/services/control" + oid "github.com/nspcc-dev/neofs-sdk-go/object/id" + "github.com/spf13/cobra" +) + +const objectFlag = "object" + +var objectCmd = &cobra.Command{ + Use: "object", + Short: "Direct object operations with storage engine", +} + +var objectStatusCmd = &cobra.Command{ + Use: "status", + Short: "Check current object status", + Args: cobra.NoArgs, + SilenceUsage: true, + RunE: objectStatus, +} + +func objectStatus(cmd *cobra.Command, _ []string) error { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + + pk := key.Get(cmd) + addressRaw, err := cmd.Flags().GetString(objectFlag) + if err != nil { + return fmt.Errorf("reading %s flag: %w", objectFlag, err) + } + + var sdkAddr oid.Address + err = sdkAddr.DecodeString(addressRaw) + if err != nil { + return fmt.Errorf("validating address (%s): %w", addressRaw, err) + } + + var resp *control.ObjectStatusResponse + req := &control.ObjectStatusRequest{ + Body: &control.ObjectStatusRequest_Body{ + ObjectAddress: addressRaw, + }, + } + signRequest(cmd, pk, req) + + cli := getClient(ctx, cmd) + + err = cli.ExecRaw(func(client *rawclient.Client) error { + resp, err = control.ObjectStatus(client, req) + return err + }) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + shards := resp.GetBody().GetShards() + if len(shards) == 0 { + cmd.Println("") + return nil + } + + for _, shard := range resp.GetBody().GetShards() { + cmd.Printf("Shard ID: %s\n", shard.ShardId) + storages := shard.GetStorages() + if len(storages) == 0 { + cmd.Println("\t") + continue + } + + for _, storage := range storages { + cmd.Printf("\t%s: %s\n", storage.Type, storage.Status) + } + } + + return nil +} + +func initObjectStatusFlags() { + initControlFlags(objectStatusCmd) + + flags := objectStatusCmd.Flags() + flags.String(objectFlag, "", "Object address") +} diff --git a/cmd/neofs-cli/modules/control/root.go b/cmd/neofs-cli/modules/control/root.go index 660be77934..c2848bfe1a 100644 --- a/cmd/neofs-cli/modules/control/root.go +++ b/cmd/neofs-cli/modules/control/root.go @@ -27,12 +27,17 @@ const ( ) func init() { + objectCmd.AddCommand( + objectStatusCmd, + ) + Cmd.AddCommand( healthCheckCmd, setNetmapStatusCmd, dropObjectsCmd, shardsCmd, synchronizeTreeCmd, + objectCmd, ) initControlHealthCheckCmd() @@ -40,4 +45,5 @@ func init() { initControlDropObjectsCmd() initControlShardsCmd() initControlSynchronizeTreeCmd() + initObjectStatusFlags() }