repo_description: Consul is a distributed, highly available, and data center aware solution to connect and configure applications across dynamic, distributed infrastructure.
repo_topics: api-gateway consul ecs kubernetes service-discovery service-mesh vault
code: // Copyright (c) HashiCorp, Inc.
  // SPDX-License-Identifier: MPL-2.0
  
  package api
  
  // RaftServer has information about a server in the Raft configuration.
  type RaftServer struct {
  	// ID is the unique ID for the server. These are currently the same
  	// as the address, but they will be changed to a real GUID in a future
  	// release of Consul.
  	ID string
  
  	// Node is the node name of the server, as known by Consul, or this
  	// will be set to "(unknown)" otherwise.
  	Node string
  
  	// Address is the IP:port of the server, used for Raft communications.
  	Address string
  
  	// Leader is true if this server is the current cluster leader.
  	Leader bool
  
  	// Protocol version is the raft protocol version used by the server
  	ProtocolVersion string
  
  	// Voter is true if this server has a vote in the cluster. This might
  	// be false if the server is staging and still coming online, or if
  	// it's a non-voting server, which will be added in a future release of
  	// Consul.
  	Voter bool
  
  	// LastIndex is the last log index this server has a record of in its Raft log.
  	LastIndex uint64
  }
  
  // RaftConfiguration is returned when querying for the current Raft configuration.
  type RaftConfiguration struct {
  	// Servers has the list of servers in the Raft configuration.
  	Servers []*RaftServer
  
  	// Index has the Raft index of this configuration.
  	Index uint64
  }
  
  // TransferLeaderResponse is returned when querying for the current Raft configuration.
  type TransferLeaderResponse struct {
  	Success bool
  }
  
  // RaftGetConfiguration is used to query the current Raft peer set.
  func (op *Operator) RaftGetConfiguration(q *QueryOptions) (*RaftConfiguration, error) {
  	r := op.c.newRequest("GET", "/v1/operator/raft/configuration")
  	r.setQueryOptions(q)
  	_, resp, err := op.c.doRequest(r)
  	if err != nil {
  		return nil, err
  	}
  	defer closeResponseBody(resp)
  	if err := requireOK(resp); err != nil {
  		return nil, err
  	}
  
  	var out RaftConfiguration
  	if err := decodeBody(resp, &out); err != nil {
  		return nil, err
  	}
  	return &out, nil
  }
  
  // RaftLeaderTransfer is used to transfer the current raft leader to another node
  // Optionally accepts a non-empty id of another node to transfer leadership to.
  func (op *Operator) RaftLeaderTransfer(id string, q *QueryOptions) (*TransferLeaderResponse, error) {
  	r := op.c.newRequest("POST", "/v1/operator/raft/transfer-leader")
  	r.setQueryOptions(q)
  
  	if id != "" {
  		r.params.Set("id", id)
  	}
  	_, resp, err := op.c.doRequest(r)
  	if err != nil {
  		return nil, err
  	}
  	defer closeResponseBody(resp)
  	if err := requireOK(resp); err != nil {
  		return nil, err
  	}
  
  	var out TransferLeaderResponse
  	if err := decodeBody(resp, &out); err != nil {
  		return nil, err
  	}
  	return &out, nil
  }
  
  // RaftRemovePeerByAddress is used to kick a stale peer (one that it in the Raft
  // quorum but no longer known to Serf or the catalog) by address in the form of
  // "IP:port".
  func (op *Operator) RaftRemovePeerByAddress(address string, q *WriteOptions) error {
  	r := op.c.newRequest("DELETE", "/v1/operator/raft/peer")
  	r.setWriteOptions(q)
  
  	r.params.Set("address", address)
  
  	_, resp, err := op.c.doRequest(r)
  	if err != nil {
  		return err
  	}
  	defer closeResponseBody(resp)
  	if err := requireOK(resp); err != nil {
  		return err
  	}
  	return nil
  }
  
  // RaftRemovePeerByID is used to kick a stale peer (one that it in the Raft
  // quorum but no longer known to Serf or the catalog) by ID.
  func (op *Operator) RaftRemovePeerByID(id string, q *WriteOptions) error {
  	r := op.c.newRequest("DELETE", "/v1/operator/raft/peer")
  	r.setWriteOptions(q)
  
  	r.params.Set("id", id)
  
  	_, resp, err := op.c.doRequest(r)
  	if err != nil {
  		return err
  	}
  	defer closeResponseBody(resp)
  	if err := requireOK(resp); err != nil {
  		return err
  	}
  	return nil
  }
  