diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c29cd3efe..30ecfa7676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Changelog for NeoFS Node - Make `morph.cache_ttl` default value equal to morph block time (#1846) - Policer marks nodes under maintenance as OK without requests (#1680) - Unify help messages in CLI (#1854) +- `evacuate`, `set-mode` and `flush-cache` control subcommands now accept a list of shard ids (#1867) ### Fixed - Description of command `netmap nodeinfo` (#1821) diff --git a/cmd/neofs-cli/modules/control/evacuate_shard.go b/cmd/neofs-cli/modules/control/evacuate_shard.go index a5aa83afc6..51cc316977 100644 --- a/cmd/neofs-cli/modules/control/evacuate_shard.go +++ b/cmd/neofs-cli/modules/control/evacuate_shard.go @@ -20,7 +20,7 @@ func evacuateShard(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) req := &control.EvacuateShardRequest{Body: new(control.EvacuateShardRequest_Body)} - req.Body.Shard_ID = [][]byte{getShardID(cmd)} + req.Body.Shard_ID = getShardIDList(cmd) req.Body.IgnoreErrors, _ = cmd.Flags().GetBool(dumpIgnoreErrorsFlag) signRequest(cmd, pk, req) @@ -47,7 +47,7 @@ func initControlEvacuateShardCmd() { flags := evacuateShardCmd.Flags() flags.String(controlRPC, controlRPCDefault, controlRPCUsage) - flags.String(shardIDFlag, "", "Shard ID in base58 encoding") + flags.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") flags.Bool(dumpIgnoreErrorsFlag, false, "Skip invalid/unreadable objects") _ = evacuateShardCmd.MarkFlagRequired(shardIDFlag) diff --git a/cmd/neofs-cli/modules/control/flush_cache.go b/cmd/neofs-cli/modules/control/flush_cache.go index f6c134b129..6f6ce43886 100644 --- a/cmd/neofs-cli/modules/control/flush_cache.go +++ b/cmd/neofs-cli/modules/control/flush_cache.go @@ -20,7 +20,7 @@ func flushCache(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) req := &control.FlushCacheRequest{Body: new(control.FlushCacheRequest_Body)} - req.Body.Shard_ID = [][]byte{getShardID(cmd)} + req.Body.Shard_ID = getShardIDList(cmd) signRequest(cmd, pk, req) @@ -44,7 +44,7 @@ func initControlFlushCacheCmd() { ff := flushCacheCmd.Flags() ff.String(controlRPC, controlRPCDefault, controlRPCUsage) - ff.String(shardIDFlag, "", "Shard ID in base58 encoding") + ff.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") _ = flushCacheCmd.MarkFlagRequired(shardIDFlag) } diff --git a/cmd/neofs-cli/modules/control/shards_set_mode.go b/cmd/neofs-cli/modules/control/shards_set_mode.go index a6af8e36ef..d4b337c181 100644 --- a/cmd/neofs-cli/modules/control/shards_set_mode.go +++ b/cmd/neofs-cli/modules/control/shards_set_mode.go @@ -1,6 +1,7 @@ package control import ( + "errors" "fmt" "github.com/mr-tron/base58" @@ -36,7 +37,7 @@ func initControlSetShardModeCmd() { flags := setShardModeCmd.Flags() flags.String(controlRPC, controlRPCDefault, controlRPCUsage) - flags.String(shardIDFlag, "", "ID of the shard in base58 encoding") + flags.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") flags.String(shardModeFlag, "", fmt.Sprintf("New shard mode keyword ('%s', '%s', '%s')", shardModeReadWrite, @@ -71,7 +72,7 @@ func setShardMode(cmd *cobra.Command, _ []string) { req.SetBody(body) body.SetMode(mode) - body.SetShardIDList([][]byte{getShardID(cmd)}) + body.SetShardIDList(getShardIDList(cmd)) reset, _ := cmd.Flags().GetBool(shardClearErrorsFlag) body.ClearErrorCounter(reset) @@ -99,3 +100,31 @@ func getShardID(cmd *cobra.Command) []byte { common.ExitOnErr(cmd, "incorrect shard ID encoding: %w", err) return raw } + +func getShardIDList(cmd *cobra.Command) [][]byte { + sidList, _ := cmd.Flags().GetStringSlice(shardIDFlag) + if len(sidList) == 0 { + common.ExitOnErr(cmd, "", errors.New("no shard IDs were provided")) + } + + // We can sort the ID list and perform this check without additional allocations, + // but preserving the user order is a nice thing to have. + // Also, this is a CLI, we don't care too much about this. + seen := make(map[string]struct{}) + for i := range sidList { + if _, ok := seen[sidList[i]]; ok { + common.ExitOnErr(cmd, "", fmt.Errorf("duplicated shard IDs: %s", sidList[i])) + } + seen[sidList[i]] = struct{}{} + } + + res := make([][]byte, 0, len(sidList)) + for i := range sidList { + raw, err := base58.Decode(sidList[i]) + common.ExitOnErr(cmd, "incorrect shard ID encoding: %w", err) + + res = append(res, raw) + } + + return res +}