/* Copyright © 2026 Thomas von Dein This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package cmd import ( "context" "errors" "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/es" "github.com/urfave/cli/v3" ) func ClusterReroute(conf *cfg.Config) *cli.Command { return &cli.Command{ Name: "reroute", Usage: "manually change the allocation of individual shards in the cluster.", UsageText: "reroute ", Aliases: []string{"ctx"}, Commands: []*cli.Command{ ClusterRerouteMove(conf), ClusterRerouteAllocateReplica(conf), ClusterRerouteCancel(conf), ClusterRerouteAllocatePrimary(conf, false), ClusterRerouteAllocatePrimary(conf, true), }, } } func ClusterRerouteMove(conf *cfg.Config) *cli.Command { return &cli.Command{ Name: "move", Usage: "move shard to another node", UsageText: "move [options] ", ShellComplete: func(ctx context.Context, cmd *cli.Command) { complete(cmd, Cindex) }, Flags: []cli.Flag{ &cli.IntFlag{ Name: "shard", Usage: "shard to move", Destination: &conf.Shards, Aliases: []string{"s"}, Required: true, }, &cli.StringFlag{ Name: "from-node", Usage: "current node", Destination: &conf.FromNode, Aliases: []string{"f"}, Required: true, }, &cli.StringFlag{ Name: "to-node", Usage: "node to move to", Destination: &conf.ToNode, Aliases: []string{"t"}, Required: true, }, }, Action: func(ctx context.Context, cmd *cli.Command) error { index := cmd.Args().Get(0) if index == "" { return errors.New("no index specified") } return es.ClusterRerouteMove(conf, index) }, } } func ClusterRerouteAllocateReplica(conf *cfg.Config) *cli.Command { return &cli.Command{ Name: "allocate-replica", Usage: "allocate-replica replica to another node", UsageText: "allocate-replica [options] ", ShellComplete: func(ctx context.Context, cmd *cli.Command) { complete(cmd, Cindex) }, Flags: []cli.Flag{ &cli.IntFlag{ Name: "shard", Usage: "shard to move", Destination: &conf.Shards, Aliases: []string{"s"}, Required: true, }, &cli.StringFlag{ Name: "to-node", Usage: "node to move to", Destination: &conf.ToNode, Aliases: []string{"t"}, Required: true, }, }, Action: func(ctx context.Context, cmd *cli.Command) error { index := cmd.Args().Get(0) if index == "" { return errors.New("no index specified") } return es.ClusterRerouteAllocateReplica(conf, index) }, } } func ClusterRerouteCancel(conf *cfg.Config) *cli.Command { return &cli.Command{ Name: "cancel", Usage: "cancel a reroute operation", UsageText: "cancel [options] ", ShellComplete: func(ctx context.Context, cmd *cli.Command) { complete(cmd, Cindex) }, Flags: []cli.Flag{ &cli.IntFlag{ Name: "shard", Usage: "shard to move", Destination: &conf.Shards, Aliases: []string{"s"}, Required: true, }, &cli.StringFlag{ Name: "to-node", Usage: "node to move to", Destination: &conf.ToNode, Aliases: []string{"t"}, Required: true, }, &cli.BoolFlag{ Name: "allow-primary", Usage: "allow primary shard to cancel", Destination: &conf.AllowPrimary, Aliases: []string{"a"}, }, }, Action: func(ctx context.Context, cmd *cli.Command) error { index := cmd.Args().Get(0) if index == "" { return errors.New("no index specified") } return es.ClusterRerouteCancel(conf, index) }, } } func ClusterRerouteAllocatePrimary(conf *cfg.Config, stale bool) *cli.Command { name := "allocate-empty-primary" usage := "allocate an empty primary shard to a node" if stale { name = "allocate-stale-primary" usage = "allocate a stale primary shard to a node" } return &cli.Command{ Name: name, Usage: usage, UsageText: name + " [options] ", ShellComplete: func(ctx context.Context, cmd *cli.Command) { complete(cmd, Cindex) }, Flags: []cli.Flag{ &cli.IntFlag{ Name: "shard", Usage: "shard to move", Destination: &conf.Shards, Aliases: []string{"s"}, Required: true, }, &cli.StringFlag{ Name: "to-node", Usage: "node to move to", Destination: &conf.ToNode, Aliases: []string{"t"}, Required: true, }, &cli.BoolFlag{ Name: "accept-data-loss", Usage: "", Destination: &conf.AcceptDataLoss, Aliases: []string{"a"}, Required: true, }, }, Action: func(ctx context.Context, cmd *cli.Command) error { index := cmd.Args().Get(0) if index == "" { return errors.New("no index specified") } return es.ClusterRerouteAllocatePrimary(conf, index, stale) }, } }