diff --git a/api/operator.go b/api/operator.go index a8d04a38eb..8f0aa661d3 100644 --- a/api/operator.go +++ b/api/operator.go @@ -63,6 +63,13 @@ type KeyringResponse struct { NumNodes int } +// AutopilotConfiguration is used for querying/setting the Autopilot configuration +type AutopilotConfiguration struct { + // DeadServerCleanup controls whether to remove dead servers from the Raft peer list + // when a new server joins + DeadServerCleanup 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") @@ -161,3 +168,33 @@ func (op *Operator) KeyringUse(key string, q *WriteOptions) error { resp.Body.Close() return nil } + +// RaftGetConfiguration is used to query the current Raft peer set. +func (op *Operator) AutopilotGetConfiguration(q *QueryOptions) (*AutopilotConfiguration, error) { + r := op.c.newRequest("GET", "/v1/operator/autopilot/configuration") + r.setQueryOptions(q) + _, resp, err := requireOK(op.c.doRequest(r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var out AutopilotConfiguration + if err := decodeBody(resp, &out); err != nil { + return nil, err + } + return &out, nil +} + +// RaftGetConfiguration is used to query the current Raft peer set. +func (op *Operator) AutopilotSetConfiguration(conf *AutopilotConfiguration, q *WriteOptions) error { + r := op.c.newRequest("PUT", "/v1/operator/autopilot/configuration") + r.setWriteOptions(q) + r.obj = conf + _, resp, err := requireOK(op.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} \ No newline at end of file diff --git a/api/operator_test.go b/api/operator_test.go index e55495e2e9..59b05545a9 100644 --- a/api/operator_test.go +++ b/api/operator_test.go @@ -104,3 +104,31 @@ func TestOperator_KeyringInstallListPutRemove(t *testing.T) { } } } + +func TestOperator_AutopilotGetSetConfiguration(t *testing.T) { + t.Parallel() + c, s := makeClient(t) + defer s.Stop() + + operator := c.Operator() + config, err := operator.AutopilotGetConfiguration(nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if !config.DeadServerCleanup { + t.Fatalf("bad: %v", config) + } + + // Change a config setting + if err := operator.AutopilotSetConfiguration(&AutopilotConfiguration{false}, nil); err != nil { + t.Fatalf("err: %v", err) + } + + config, err = operator.AutopilotGetConfiguration(nil) + if err != nil { + t.Fatalf("err: %v", err) + } + if config.DeadServerCleanup { + t.Fatalf("bad: %v", config) + } +} \ No newline at end of file diff --git a/website/source/docs/agent/http/operator.html.markdown b/website/source/docs/agent/http/operator.html.markdown index 7b6bdd52e9..a75b1d08d4 100644 --- a/website/source/docs/agent/http/operator.html.markdown +++ b/website/source/docs/agent/http/operator.html.markdown @@ -28,6 +28,7 @@ The following endpoints are supported: * [`/v1/operator/raft/configuration`](#raft-configuration): Inspects the Raft configuration * [`/v1/operator/raft/peer`](#raft-peer): Operates on Raft peers * [`/v1/operator/keyring`](#keyring): Operates on gossip keyring +* [`/v1/operator/autopilot/configuration`](#autopilot-configuration): Operates on the Autopilot configuration Not all endpoints support blocking queries and all consistency modes, see details in the sections below. @@ -258,3 +259,59 @@ If ACLs are enabled, the client will need to supply an ACL Token with [`keyring`](/docs/internals/acl.html#keyring) write privileges. The return code will indicate success or failure. + +### /v1/operator/autopilot/configuration + +Available in Consul 0.8.0 and later, the autopilot configuration endpoint supports the +`GET` and `PUT` methods. + +This endpoint supports the use of ACL tokens using either the `X-CONSUL-TOKEN` +header or the `?token=` query parameter. + +By default, the datacenter of the agent is queried; however, the `dc` can be +provided using the `?dc=` query parameter. + +#### GET Method + +When using the `GET` method, the request will be forwarded to the cluster +leader to retrieve its latest Autopilot configuration. + +If the cluster doesn't currently have a leader an error will be returned. You +can use the `?stale` query parameter to read the Raft configuration from any +of the Consul servers. + +If ACLs are enabled, the client will need to supply an ACL Token with +[`operator`](/docs/internals/acl.html#operator) read privileges. + +A JSON body is returned that looks like this: + +```javascript +{ + "DeadServerCleanup": true +} +``` + +`DeadServerCleanup` is whether dead servers should be removed automatically when +a new server is added to the cluster. + +#### PUT Method + +Using the `PUT` method, this endpoint will update the Autopilot configuration +of the cluster. + +If ACLs are enabled, the client will need to supply an ACL Token with +[`operator`](/docs/internals/acl.html#operator) write privileges. + +The `PUT` method expects a JSON request body to be submitted. The request +body must look like: + +```javascript +{ + "DeadServerCleanup": true +} +``` + +`DeadServerCleanup` is whether dead servers should be removed automatically when +a new server is added to the cluster. + +The return code will indicate success or failure.