diff --git a/command/commands.go b/command/commands.go index 634b2491a2..75e17cdf6b 100644 --- a/command/commands.go +++ b/command/commands.go @@ -30,6 +30,7 @@ import ( "github.com/hashicorp/consul/command/oper" "github.com/hashicorp/consul/command/operraft" "github.com/hashicorp/consul/command/operraftlist" + "github.com/hashicorp/consul/command/operraftremove" "github.com/hashicorp/consul/command/validate" "github.com/hashicorp/consul/version" "github.com/mitchellh/cli" @@ -184,12 +185,7 @@ func init() { }, "operator raft remove-peer": func() (cli.Command, error) { - return &OperatorRaftRemoveCommand{ - BaseCommand: BaseCommand{ - Flags: FlagSetHTTP, - UI: ui, - }, - }, nil + return operraftremove.New(ui), nil }, "reload": func() (cli.Command, error) { diff --git a/command/operator_raft_remove.go b/command/operraftremove/operator_raft_remove.go similarity index 67% rename from command/operator_raft_remove.go rename to command/operraftremove/operator_raft_remove.go index 7ab80336f1..3c1edfbcb7 100644 --- a/command/operator_raft_remove.go +++ b/command/operraftremove/operator_raft_remove.go @@ -1,52 +1,54 @@ -package command +package operraftremove import ( "flag" "fmt" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/command/flags" + "github.com/mitchellh/cli" ) -type OperatorRaftRemoveCommand struct { - BaseCommand +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + http *flags.HTTPFlags + usage string // flags address string id string } -func (c *OperatorRaftRemoveCommand) initFlags() { - c.InitFlagSet() - c.FlagSet.StringVar(&c.address, "address", "", +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.StringVar(&c.address, "address", "", "The address to remove from the Raft configuration.") - c.FlagSet.StringVar(&c.id, "id", "", + c.flags.StringVar(&c.id, "id", "", "The ID to remove from the Raft configuration.") + + c.http = &flags.HTTPFlags{} + flags.Merge(c.flags, c.http.ClientFlags()) + flags.Merge(c.flags, c.http.ServerFlags()) + c.usage = flags.Usage(usage, c.flags, c.http.ClientFlags(), c.http.ServerFlags()) } -func (c *OperatorRaftRemoveCommand) Help() string { - c.initFlags() - return c.HelpCommand(` -Usage: consul operator raft remove-peer [options] - -Remove the Consul server with given -address from the Raft configuration. - -There are rare cases where a peer may be left behind in the Raft quorum even -though the server is no longer present and known to the cluster. This command -can be used to remove the failed server so that it is no longer affects the Raft -quorum. If the server still shows in the output of the "consul members" command, -it is preferable to clean up by simply running "consul force-leave" instead of -this command. - -`) -} - -func (c *OperatorRaftRemoveCommand) Synopsis() string { +func (c *cmd) Synopsis() string { return "Remove a Consul server from the Raft configuration" } -func (c *OperatorRaftRemoveCommand) Run(args []string) int { - c.initFlags() - if err := c.FlagSet.Parse(args); err != nil { +func (c *cmd) Help() string { + return c.usage +} + +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { if err == flag.ErrHelp { return 0 } @@ -55,7 +57,7 @@ func (c *OperatorRaftRemoveCommand) Run(args []string) int { } // Set up a client. - client, err := c.HTTPClient() + client, err := c.http.APIClient() if err != nil { c.UI.Error(fmt.Sprintf("Error initializing client: %s", err)) return 1 @@ -96,3 +98,14 @@ func raftRemovePeers(address, id string, operator *api.Operator) error { return nil } + +const usage = `Usage: consul operator raft remove-peer [options] + +Remove the Consul server with given -address from the Raft configuration. + +There are rare cases where a peer may be left behind in the Raft quorum even +though the server is no longer present and known to the cluster. This command +can be used to remove the failed server so that it is no longer affects the Raft +quorum. If the server still shows in the output of the "consul members" command, +it is preferable to clean up by simply running "consul force-leave" instead of +this command.` diff --git a/command/operator_raft_remove_test.go b/command/operraftremove/operator_raft_remove_test.go similarity index 71% rename from command/operator_raft_remove_test.go rename to command/operraftremove/operator_raft_remove_test.go index 2aa6f59c82..90c600b6f0 100644 --- a/command/operator_raft_remove_test.go +++ b/command/operraftremove/operator_raft_remove_test.go @@ -1,4 +1,4 @@ -package command +package operraftremove import ( "strings" @@ -8,9 +8,11 @@ import ( "github.com/mitchellh/cli" ) -func TestOperator_Raft_RemovePeer_Implements(t *testing.T) { +func TestOperatorRaftRemovePeerCommand_noTabs(t *testing.T) { t.Parallel() - var _ cli.Command = &OperatorRaftRemoveCommand{} + if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') { + t.Fatal("usage has tabs") + } } func TestOperator_Raft_RemovePeer(t *testing.T) { @@ -18,15 +20,9 @@ func TestOperator_Raft_RemovePeer(t *testing.T) { a := agent.NewTestAgent(t.Name(), ``) defer a.Shutdown() - // Test the remove-peer subcommand directly - { + t.Run("Test the remove-peer subcommand directly", func(t *testing.T) { ui := cli.NewMockUi() - c := OperatorRaftRemoveCommand{ - BaseCommand: BaseCommand{ - UI: ui, - Flags: FlagSetHTTP, - }, - } + c := New(ui) args := []string{"-http-addr=" + a.HTTPAddr(), "-address=nope"} code := c.Run(args) @@ -39,17 +35,11 @@ func TestOperator_Raft_RemovePeer(t *testing.T) { if !strings.Contains(output, "address \"nope\" was not found in the Raft configuration") { t.Fatalf("bad: %s", output) } - } + }) - // Test the remove-peer subcommand with -id - { + t.Run("Test the remove-peer subcommand with -id", func(t *testing.T) { ui := cli.NewMockUi() - c := OperatorRaftRemoveCommand{ - BaseCommand: BaseCommand{ - UI: ui, - Flags: FlagSetHTTP, - }, - } + c := New(ui) args := []string{"-http-addr=" + a.HTTPAddr(), "-id=nope"} code := c.Run(args) @@ -62,5 +52,5 @@ func TestOperator_Raft_RemovePeer(t *testing.T) { if !strings.Contains(output, "id \"nope\" was not found in the Raft configuration") { t.Fatalf("bad: %s", output) } - } + }) }