1package api
2
3// Operator can be used to perform low-level operator tasks for Consul.
4type Operator struct {
5	c *Client
6}
7
8// Operator returns a handle to the operator endpoints.
9func (c *Client) Operator() *Operator {
10	return &Operator{c}
11}
12
13// RaftServer has information about a server in the Raft configuration.
14type RaftServer struct {
15	// ID is the unique ID for the server. These are currently the same
16	// as the address, but they will be changed to a real GUID in a future
17	// release of Consul.
18	ID string
19
20	// Node is the node name of the server, as known by Consul, or this
21	// will be set to "(unknown)" otherwise.
22	Node string
23
24	// Address is the IP:port of the server, used for Raft communications.
25	Address string
26
27	// Leader is true if this server is the current cluster leader.
28	Leader bool
29
30	// Voter is true if this server has a vote in the cluster. This might
31	// be false if the server is staging and still coming online, or if
32	// it's a non-voting server, which will be added in a future release of
33	// Consul.
34	Voter bool
35}
36
37// RaftConfigration is returned when querying for the current Raft configuration.
38type RaftConfiguration struct {
39	// Servers has the list of servers in the Raft configuration.
40	Servers []*RaftServer
41
42	// Index has the Raft index of this configuration.
43	Index uint64
44}
45
46// keyringRequest is used for performing Keyring operations
47type keyringRequest struct {
48	Key string
49}
50
51// KeyringResponse is returned when listing the gossip encryption keys
52type KeyringResponse struct {
53	// Whether this response is for a WAN ring
54	WAN bool
55
56	// The datacenter name this request corresponds to
57	Datacenter string
58
59	// A map of the encryption keys to the number of nodes they're installed on
60	Keys map[string]int
61
62	// The total number of nodes in this ring
63	NumNodes int
64}
65
66// RaftGetConfiguration is used to query the current Raft peer set.
67func (op *Operator) RaftGetConfiguration(q *QueryOptions) (*RaftConfiguration, error) {
68	r := op.c.newRequest("GET", "/v1/operator/raft/configuration")
69	r.setQueryOptions(q)
70	_, resp, err := requireOK(op.c.doRequest(r))
71	if err != nil {
72		return nil, err
73	}
74	defer resp.Body.Close()
75
76	var out RaftConfiguration
77	if err := decodeBody(resp, &out); err != nil {
78		return nil, err
79	}
80	return &out, nil
81}
82
83// RaftRemovePeerByAddress is used to kick a stale peer (one that it in the Raft
84// quorum but no longer known to Serf or the catalog) by address in the form of
85// "IP:port".
86func (op *Operator) RaftRemovePeerByAddress(address string, q *WriteOptions) error {
87	r := op.c.newRequest("DELETE", "/v1/operator/raft/peer")
88	r.setWriteOptions(q)
89
90	// TODO (slackpad) Currently we made address a query parameter. Once
91	// IDs are in place this will be DELETE /v1/operator/raft/peer/<id>.
92	r.params.Set("address", string(address))
93
94	_, resp, err := requireOK(op.c.doRequest(r))
95	if err != nil {
96		return err
97	}
98
99	resp.Body.Close()
100	return nil
101}
102
103// KeyringInstall is used to install a new gossip encryption key into the cluster
104func (op *Operator) KeyringInstall(key string, q *WriteOptions) error {
105	r := op.c.newRequest("POST", "/v1/operator/keyring")
106	r.setWriteOptions(q)
107	r.obj = keyringRequest{
108		Key: key,
109	}
110	_, resp, err := requireOK(op.c.doRequest(r))
111	if err != nil {
112		return err
113	}
114	resp.Body.Close()
115	return nil
116}
117
118// KeyringList is used to list the gossip keys installed in the cluster
119func (op *Operator) KeyringList(q *QueryOptions) ([]*KeyringResponse, error) {
120	r := op.c.newRequest("GET", "/v1/operator/keyring")
121	r.setQueryOptions(q)
122	_, resp, err := requireOK(op.c.doRequest(r))
123	if err != nil {
124		return nil, err
125	}
126	defer resp.Body.Close()
127
128	var out []*KeyringResponse
129	if err := decodeBody(resp, &out); err != nil {
130		return nil, err
131	}
132	return out, nil
133}
134
135// KeyringRemove is used to remove a gossip encryption key from the cluster
136func (op *Operator) KeyringRemove(key string, q *WriteOptions) error {
137	r := op.c.newRequest("DELETE", "/v1/operator/keyring")
138	r.setWriteOptions(q)
139	r.obj = keyringRequest{
140		Key: key,
141	}
142	_, resp, err := requireOK(op.c.doRequest(r))
143	if err != nil {
144		return err
145	}
146	resp.Body.Close()
147	return nil
148}
149
150// KeyringUse is used to change the active gossip encryption key
151func (op *Operator) KeyringUse(key string, q *WriteOptions) error {
152	r := op.c.newRequest("PUT", "/v1/operator/keyring")
153	r.setWriteOptions(q)
154	r.obj = keyringRequest{
155		Key: key,
156	}
157	_, resp, err := requireOK(op.c.doRequest(r))
158	if err != nil {
159		return err
160	}
161	resp.Body.Close()
162	return nil
163}
164