github.com/sl1pm4t/consul@v1.4.5-0.20190325224627-74c31c540f9c/command/operator/raft/removepeer/operator_raft_remove.go (about) 1 package removepeer 2 3 import ( 4 "flag" 5 "fmt" 6 7 "github.com/hashicorp/consul/api" 8 "github.com/hashicorp/consul/command/flags" 9 "github.com/mitchellh/cli" 10 ) 11 12 func New(ui cli.Ui) *cmd { 13 c := &cmd{UI: ui} 14 c.init() 15 return c 16 } 17 18 type cmd struct { 19 UI cli.Ui 20 flags *flag.FlagSet 21 http *flags.HTTPFlags 22 help string 23 24 // flags 25 address string 26 id string 27 } 28 29 func (c *cmd) init() { 30 c.flags = flag.NewFlagSet("", flag.ContinueOnError) 31 c.flags.StringVar(&c.address, "address", "", 32 "The address to remove from the Raft configuration.") 33 c.flags.StringVar(&c.id, "id", "", 34 "The ID to remove from the Raft configuration.") 35 36 c.http = &flags.HTTPFlags{} 37 flags.Merge(c.flags, c.http.ClientFlags()) 38 flags.Merge(c.flags, c.http.ServerFlags()) 39 c.help = flags.Usage(help, c.flags) 40 } 41 42 func (c *cmd) Run(args []string) int { 43 if err := c.flags.Parse(args); err != nil { 44 if err == flag.ErrHelp { 45 return 0 46 } 47 c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err)) 48 return 1 49 } 50 51 // Set up a client. 52 client, err := c.http.APIClient() 53 if err != nil { 54 c.UI.Error(fmt.Sprintf("Error initializing client: %s", err)) 55 return 1 56 } 57 58 // Fetch the current configuration. 59 if err := raftRemovePeers(c.address, c.id, client.Operator()); err != nil { 60 c.UI.Error(fmt.Sprintf("Error removing peer: %v", err)) 61 return 1 62 } 63 if c.address != "" { 64 c.UI.Output(fmt.Sprintf("Removed peer with address %q", c.address)) 65 } else { 66 c.UI.Output(fmt.Sprintf("Removed peer with id %q", c.id)) 67 } 68 69 return 0 70 } 71 72 func raftRemovePeers(address, id string, operator *api.Operator) error { 73 if len(address) == 0 && len(id) == 0 { 74 return fmt.Errorf("an address or id is required for the peer to remove") 75 } 76 if len(address) > 0 && len(id) > 0 { 77 return fmt.Errorf("cannot give both an address and id") 78 } 79 80 // Try to kick the peer. 81 if len(address) > 0 { 82 if err := operator.RaftRemovePeerByAddress(address, nil); err != nil { 83 return err 84 } 85 } else { 86 if err := operator.RaftRemovePeerByID(id, nil); err != nil { 87 return err 88 } 89 } 90 91 return nil 92 } 93 94 func (c *cmd) Synopsis() string { 95 return synopsis 96 } 97 98 func (c *cmd) Help() string { 99 return c.help 100 } 101 102 const synopsis = "Remove a Consul server from the Raft configuration" 103 const help = ` 104 Usage: consul operator raft remove-peer [options] 105 106 Remove the Consul server with given -address from the Raft configuration. 107 108 There are rare cases where a peer may be left behind in the Raft quorum even 109 though the server is no longer present and known to the cluster. This command 110 can be used to remove the failed server so that it is no longer affects the Raft 111 quorum. If the server still shows in the output of the "consul members" command, 112 it is preferable to clean up by simply running "consul force-leave" instead of 113 this command. 114 `