0758c73ef3
The format of the missing port error message changed from Go 1.7 to 1.8. The fix is to just use strings.Contains instead of strings.HasPrefix when looking for the "missing port" part. Also add an error return to Client.newRequest as parsing the path processes arbitrary user input and would panic if given an invalid URL. See: https://groups.google.com/d/topic/nomad-tool/gi3-CTE7oXo/discussion
88 lines
2.4 KiB
Go
88 lines
2.4 KiB
Go
package api
|
|
|
|
// Operator can be used to perform low-level operator tasks for Nomad.
|
|
type Operator struct {
|
|
c *Client
|
|
}
|
|
|
|
// Operator returns a handle to the operator endpoints.
|
|
func (c *Client) Operator() *Operator {
|
|
return &Operator{c}
|
|
}
|
|
|
|
// 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 Nomad.
|
|
ID string
|
|
|
|
// Node is the node name of the server, as known by Nomad, 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
|
|
|
|
// 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
|
|
// Nomad.
|
|
Voter bool
|
|
}
|
|
|
|
// RaftConfigration 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
|
|
}
|
|
|
|
// RaftGetConfiguration is used to query the current Raft peer set.
|
|
func (op *Operator) RaftGetConfiguration(q *QueryOptions) (*RaftConfiguration, error) {
|
|
r, err := op.c.newRequest("GET", "/v1/operator/raft/configuration")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.setQueryOptions(q)
|
|
_, resp, err := requireOK(op.c.doRequest(r))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
var out RaftConfiguration
|
|
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, err := op.c.newRequest("DELETE", "/v1/operator/raft/peer")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.setWriteOptions(q)
|
|
|
|
// TODO (alexdadgar) Currently we made address a query parameter. Once
|
|
// IDs are in place this will be DELETE /v1/operator/raft/peer/<id>.
|
|
r.params.Set("address", string(address))
|
|
|
|
_, resp, err := requireOK(op.c.doRequest(r))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
resp.Body.Close()
|
|
return nil
|
|
}
|