From c55d11f8b547cf959c56805f2ecc15e6772d9e5d Mon Sep 17 00:00:00 2001 From: Sohaib Iftikhar Date: Mon, 2 Jul 2018 19:25:17 +0200 Subject: [PATCH] rest-high-level: added get cluster settings (#31706) Relates to #27205 --- .../elasticsearch/client/ClusterClient.java | 31 ++++ .../client/RequestConverters.java | 16 +- .../elasticsearch/client/ClusterClientIT.java | 43 +++++ .../client/ESRestHighLevelClientTestCase.java | 10 ++ .../client/RequestConvertersTests.java | 42 +++-- .../ClusterClientDocumentationIT.java | 68 ++++++++ .../high-level/cluster/get_settings.asciidoc | 92 ++++++++++ .../high-level/supported-apis.asciidoc | 2 + docs/reference/cluster.asciidoc | 2 + docs/reference/cluster/get-settings.asciidoc | 20 +++ .../settings/ClusterGetSettingsRequest.java | 48 +++++ .../settings/ClusterGetSettingsResponse.java | 165 ++++++++++++++++++ .../cluster/RestClusterGetSettingsAction.java | 28 ++- .../ClusterGetSettingsResponseTests.java | 57 ++++++ 14 files changed, 591 insertions(+), 33 deletions(-) create mode 100644 docs/java-rest/high-level/cluster/get_settings.asciidoc create mode 100644 docs/reference/cluster/get-settings.asciidoc create mode 100644 server/src/main/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsRequest.java create mode 100644 server/src/main/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsResponse.java create mode 100644 server/src/test/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsResponseTests.java diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java index b3075a2fddb..b72a21ed7d1 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java @@ -22,6 +22,8 @@ package org.elasticsearch.client; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; import org.elasticsearch.rest.RestStatus; @@ -72,6 +74,35 @@ public final class ClusterClient { options, ClusterUpdateSettingsResponse::fromXContent, listener, emptySet()); } + /** + * Get the cluster wide settings using the Cluster Get Settings API. + * See Cluster Get Settings + * API on elastic.co + * @param clusterGetSettingsRequest the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @return the response + * @throws IOException in case there is a problem sending the request or parsing back the response + */ + public ClusterGetSettingsResponse getSettings(ClusterGetSettingsRequest clusterGetSettingsRequest, RequestOptions options) + throws IOException { + return restHighLevelClient.performRequestAndParseEntity(clusterGetSettingsRequest, RequestConverters::clusterGetSettings, + options, ClusterGetSettingsResponse::fromXContent, emptySet()); + } + + /** + * Asynchronously get the cluster wide settings using the Cluster Get Settings API. + * See Cluster Get Settings + * API on elastic.co + * @param clusterGetSettingsRequest the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @param listener the listener to be notified upon request completion + */ + public void getSettingsAsync(ClusterGetSettingsRequest clusterGetSettingsRequest, RequestOptions options, + ActionListener listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(clusterGetSettingsRequest, RequestConverters::clusterGetSettings, + options, ClusterGetSettingsResponse::fromXContent, listener, emptySet()); + } + /** * Get cluster health using the Cluster Health API. * See diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java index 839d86bf9f1..ee4b56e8a3b 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java @@ -36,6 +36,7 @@ import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteReposito import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest; import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest; import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest; import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest; @@ -605,7 +606,7 @@ final class RequestConverters { request.setEntity(createEntity(searchTemplateRequest, REQUEST_BODY_CONTENT_TYPE)); return request; } - + static Request multiSearchTemplate(MultiSearchTemplateRequest multiSearchTemplateRequest) throws IOException { Request request = new Request(HttpPost.METHOD_NAME, "/_msearch/template"); @@ -619,7 +620,7 @@ final class RequestConverters { byte[] source = MultiSearchTemplateRequest.writeMultiLineFormat(multiSearchTemplateRequest, xContent); request.setEntity(new ByteArrayEntity(source, createContentType(xContent.type()))); return request; - } + } static Request existsAlias(GetAliasesRequest getAliasesRequest) { if ((getAliasesRequest.indices() == null || getAliasesRequest.indices().length == 0) && @@ -709,6 +710,17 @@ final class RequestConverters { return request; } + static Request clusterGetSettings(ClusterGetSettingsRequest clusterGetSettingsRequest) throws IOException { + Request request = new Request(HttpGet.METHOD_NAME, "/_cluster/settings"); + + Params parameters = new Params(request); + parameters.withLocal(clusterGetSettingsRequest.local()); + parameters.withIncludeDefaults(clusterGetSettingsRequest.includeDefaults()); + parameters.withMasterTimeout(clusterGetSettingsRequest.masterNodeTimeout()); + + return request; + } + static Request getPipeline(GetPipelineRequest getPipelineRequest) { String endpoint = new EndpointBuilder() .addPathPartAsIs("_ingest/pipeline") diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java index 2a870ec65ee..58b4b268788 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java @@ -22,6 +22,8 @@ package org.elasticsearch.client; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; import org.elasticsearch.cluster.health.ClusterHealthStatus; @@ -42,6 +44,7 @@ import java.util.Map; import static java.util.Collections.emptyMap; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; @@ -112,6 +115,46 @@ public class ClusterClientIT extends ESRestHighLevelClientTestCase { "Elasticsearch exception [type=illegal_argument_exception, reason=transient setting [" + setting + "], not recognized]")); } + public void testClusterGetSettings() throws IOException { + final String transientSettingKey = RecoverySettings.INDICES_RECOVERY_MAX_BYTES_PER_SEC_SETTING.getKey(); + final int transientSettingValue = 10; + + final String persistentSettingKey = EnableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_ENABLE_SETTING.getKey(); + final String persistentSettingValue = EnableAllocationDecider.Allocation.NONE.name(); + + Settings transientSettings = + Settings.builder().put(transientSettingKey, transientSettingValue, ByteSizeUnit.BYTES).build(); + Settings persistentSettings = Settings.builder().put(persistentSettingKey, persistentSettingValue).build(); + clusterUpdateSettings(persistentSettings, transientSettings); + + ClusterGetSettingsRequest request = new ClusterGetSettingsRequest(); + ClusterGetSettingsResponse response = execute( + request, highLevelClient().cluster()::getSettings, highLevelClient().cluster()::getSettingsAsync); + assertEquals(persistentSettings, response.getPersistentSettings()); + assertEquals(transientSettings, response.getTransientSettings()); + assertEquals(0, response.getDefaultSettings().size()); + } + + public void testClusterGetSettingsWithDefault() throws IOException { + final String transientSettingKey = RecoverySettings.INDICES_RECOVERY_MAX_BYTES_PER_SEC_SETTING.getKey(); + final int transientSettingValue = 10; + + final String persistentSettingKey = EnableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_ENABLE_SETTING.getKey(); + final String persistentSettingValue = EnableAllocationDecider.Allocation.NONE.name(); + + Settings transientSettings = + Settings.builder().put(transientSettingKey, transientSettingValue, ByteSizeUnit.BYTES).build(); + Settings persistentSettings = Settings.builder().put(persistentSettingKey, persistentSettingValue).build(); + clusterUpdateSettings(persistentSettings, transientSettings); + + ClusterGetSettingsRequest request = new ClusterGetSettingsRequest().includeDefaults(true); + ClusterGetSettingsResponse response = execute( + request, highLevelClient().cluster()::getSettings, highLevelClient().cluster()::getSettingsAsync); + assertEquals(persistentSettings, response.getPersistentSettings()); + assertEquals(transientSettings, response.getTransientSettings()); + assertThat(response.getDefaultSettings().size(), greaterThan(0)); + } + public void testClusterHealthGreen() throws IOException { ClusterHealthRequest request = new ClusterHealthRequest(); request.timeout("5s"); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java index 69fbab30c33..e05fa9fa79b 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java @@ -20,9 +20,11 @@ package org.elasticsearch.client; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.ingest.PutPipelineRequest; import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.ingest.Pipeline; @@ -126,4 +128,12 @@ public abstract class ESRestHighLevelClientTestCase extends ESRestTestCase { protected static void createPipeline(PutPipelineRequest putPipelineRequest) throws IOException { assertOK(client().performRequest(RequestConverters.putPipeline(putPipelineRequest))); } + + protected static void clusterUpdateSettings(Settings persistentSettings, + Settings transientSettings) throws IOException { + ClusterUpdateSettingsRequest request = new ClusterUpdateSettingsRequest(); + request.persistentSettings(persistentSettings); + request.transientSettings(transientSettings); + assertOK(client().performRequest(RequestConverters.clusterPutSettings(request))); + } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java index e838989a0c8..ce72ecc8a59 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java @@ -36,6 +36,7 @@ import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteReposito import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest; import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest; import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest; import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest; @@ -1374,42 +1375,42 @@ public class RequestConvertersTests extends ESTestCase { assertEquals(Collections.emptyMap(), request.getParameters()); assertToXContentBody(searchTemplateRequest, request.getEntity()); } - + public void testMultiSearchTemplate() throws Exception { final int numSearchRequests = randomIntBetween(1, 10); MultiSearchTemplateRequest multiSearchTemplateRequest = new MultiSearchTemplateRequest(); - + for (int i = 0; i < numSearchRequests; i++) { // Create a random request. String[] indices = randomIndicesNames(0, 5); SearchRequest searchRequest = new SearchRequest(indices); - + Map expectedParams = new HashMap<>(); setRandomSearchParams(searchRequest, expectedParams); - + // scroll is not supported in the current msearch or msearchtemplate api, so unset it: searchRequest.scroll((Scroll) null); // batched reduce size is currently not set-able on a per-request basis as it is a query string parameter only searchRequest.setBatchedReduceSize(SearchRequest.DEFAULT_BATCHED_REDUCE_SIZE); - + setRandomIndicesOptions(searchRequest::indicesOptions, searchRequest::indicesOptions, expectedParams); - + SearchTemplateRequest searchTemplateRequest = new SearchTemplateRequest(searchRequest); - + searchTemplateRequest.setScript("{\"query\": { \"match\" : { \"{{field}}\" : \"{{value}}\" }}}"); searchTemplateRequest.setScriptType(ScriptType.INLINE); searchTemplateRequest.setProfile(randomBoolean()); - + Map scriptParams = new HashMap<>(); scriptParams.put("field", "name"); scriptParams.put("value", randomAlphaOfLengthBetween(2, 5)); searchTemplateRequest.setScriptParams(scriptParams); - - multiSearchTemplateRequest.add(searchTemplateRequest); + + multiSearchTemplateRequest.add(searchTemplateRequest); } Request multiRequest = RequestConverters.multiSearchTemplate(multiSearchTemplateRequest); - + assertEquals(HttpPost.METHOD_NAME, multiRequest.getMethod()); assertEquals("/_msearch/template", multiRequest.getEndpoint()); List searchRequests = multiSearchTemplateRequest.requests(); @@ -1418,9 +1419,9 @@ public class RequestConvertersTests extends ESTestCase { HttpEntity actualEntity = multiRequest.getEntity(); byte[] expectedBytes = MultiSearchTemplateRequest.writeMultiLineFormat(multiSearchTemplateRequest, XContentType.JSON.xContent()); assertEquals(XContentType.JSON.mediaTypeWithoutParameters(), actualEntity.getContentType().getValue()); - assertEquals(new BytesArray(expectedBytes), new BytesArray(EntityUtils.toByteArray(actualEntity))); + assertEquals(new BytesArray(expectedBytes), new BytesArray(EntityUtils.toByteArray(actualEntity))); } - + public void testExistsAlias() { GetAliasesRequest getAliasesRequest = new GetAliasesRequest(); String[] indices = randomBoolean() ? null : randomIndicesNames(0, 5); @@ -1636,6 +1637,21 @@ public class RequestConvertersTests extends ESTestCase { assertEquals(expectedParams, expectedRequest.getParameters()); } + public void testClusterGetSettings() throws IOException { + ClusterGetSettingsRequest request = new ClusterGetSettingsRequest(); + Map expectedParams = new HashMap<>(); + setRandomMasterTimeout(request, expectedParams); + request.includeDefaults(randomBoolean()); + if (request.includeDefaults()) { + expectedParams.put("include_defaults", String.valueOf(true)); + } + + Request expectedRequest = RequestConverters.clusterGetSettings(request); + assertEquals("/_cluster/settings", expectedRequest.getEndpoint()); + assertEquals(HttpGet.METHOD_NAME, expectedRequest.getMethod()); + assertEquals(expectedParams, expectedRequest.getParameters()); + } + public void testPutPipeline() throws IOException { String pipelineId = "some_pipeline_id"; PutPipelineRequest request = new PutPipelineRequest( diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java index 84a124f764b..dedd50096f8 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java @@ -23,6 +23,8 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.LatchedActionListener; import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; @@ -49,6 +51,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.notNullValue; /** @@ -189,6 +192,71 @@ public class ClusterClientDocumentationIT extends ESRestHighLevelClientTestCase } } + public void testClusterGetSettings() throws IOException { + RestHighLevelClient client = highLevelClient(); + + // tag::get-settings-request + ClusterGetSettingsRequest request = new ClusterGetSettingsRequest(); + // end::get-settings-request + + // tag::get-settings-request-includeDefaults + request.includeDefaults(true); // <1> + // end::get-settings-request-includeDefaults + + // tag::get-settings-request-local + request.local(true); // <1> + // end::get-settings-request-local + + // tag::get-settings-request-masterTimeout + request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1> + request.masterNodeTimeout("1m"); // <2> + // end::get-settings-request-masterTimeout + + // tag::get-settings-execute + ClusterGetSettingsResponse response = client.cluster().getSettings(request, RequestOptions.DEFAULT); // <1> + // end::get-settings-execute + + // tag::get-settings-response + Settings persistentSettings = response.getPersistentSettings(); // <1> + Settings transientSettings = response.getTransientSettings(); // <2> + Settings defaultSettings = response.getDefaultSettings(); // <3> + String settingValue = response.getSetting("cluster.routing.allocation.enable"); // <4> + // end::get-settings-response + + assertThat(defaultSettings.size(), greaterThan(0)); + } + + public void testClusterGetSettingsAsync() throws InterruptedException { + RestHighLevelClient client = highLevelClient(); + + ClusterGetSettingsRequest request = new ClusterGetSettingsRequest(); + + // tag::get-settings-execute-listener + ActionListener listener = + new ActionListener() { + @Override + public void onResponse(ClusterGetSettingsResponse response) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }; + // end::get-settings-execute-listener + + // Replace the empty listener by a blocking listener in test + final CountDownLatch latch = new CountDownLatch(1); + listener = new LatchedActionListener<>(listener, latch); + + // tag::get-settings-execute-async + client.cluster().getSettingsAsync(request, RequestOptions.DEFAULT, listener); // <1> + // end::get-settings-execute-async + + assertTrue(latch.await(30L, TimeUnit.SECONDS)); + } + public void testClusterHealth() throws IOException { RestHighLevelClient client = highLevelClient(); client.indices().create(new CreateIndexRequest("index"), RequestOptions.DEFAULT); diff --git a/docs/java-rest/high-level/cluster/get_settings.asciidoc b/docs/java-rest/high-level/cluster/get_settings.asciidoc new file mode 100644 index 00000000000..999bd92d791 --- /dev/null +++ b/docs/java-rest/high-level/cluster/get_settings.asciidoc @@ -0,0 +1,92 @@ +[[java-rest-high-cluster-get-settings]] +=== Cluster Get Settings API + +The Cluster Get Settings API allows to get the cluster wide settings. + +[[java-rest-high-cluster-get-settings-request]] +==== Cluster Get Settings Request + +A `ClusterGetSettingsRequest`: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[get-settings-request] +-------------------------------------------------- + +==== Optional arguments +The following arguments can optionally be provided: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[get-settings-request-includeDefaults] +-------------------------------------------------- +<1> By default only those settings that were explicitly set are returned. Setting this to true also returns +the default settings. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[get-settings-request-local] +-------------------------------------------------- +<1> By default the request goes to the master of the cluster to get the latest results. If local is specified it gets +the results from whichever node the request goes to. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[get-settings-request-masterTimeout] +-------------------------------------------------- +<1> Timeout to connect to the master node as a `TimeValue` +<2> Timeout to connect to the master node as a `String` + +[[java-rest-high-cluster-get-settings-sync]] +==== Synchronous Execution + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[get-settings-execute] +-------------------------------------------------- +<1> Execute the request and get back the response in a `ClusterGetSettingsResponse` object. + +[[java-rest-high-cluster-get-settings-async]] +==== Asynchronous Execution + +The asynchronous execution of a cluster get settings requires both the +`ClusterGetSettingsRequest` instance and an `ActionListener` instance to be +passed to the asynchronous method: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[get-settings-execute-async] +-------------------------------------------------- +<1> The `ClusterGetSettingsRequest` to execute and the `ActionListener` +to use when the execution completes + +The asynchronous method does not block and returns immediately. Once it is +completed the `ActionListener` is called back using the `onResponse` method +if the execution successfully completed or using the `onFailure` method if +it failed. + +A typical listener for `ClusterGetSettingsResponse` looks like: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[get-settings-execute-listener] +-------------------------------------------------- +<1> Called when the execution is successfully completed. The response is +provided as an argument +<2> Called in case of a failure. The raised exception is provided as an argument + +[[java-rest-high-cluster-get-settings-response]] +==== Cluster Get Settings Response + +The returned `ClusterGetSettingsResponse` allows to retrieve information about the +executed operation as follows: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[get-settings-response] +-------------------------------------------------- +<1> Get the persistent settings. +<2> Get the transient settings. +<3> Get the default settings (returns empty settings if `includeDefaults` was not set to `true`). +<4> Get the value as a `String` for a particular setting. The order of searching is first in `persistentSettings` then in +`transientSettings` and finally, if not found in either, in `defaultSettings`. diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index d2484db1d78..93513a042ad 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -118,9 +118,11 @@ include::indices/get_templates.asciidoc[] The Java High Level REST Client supports the following Cluster APIs: * <> +* <> * <> include::cluster/put_settings.asciidoc[] +include::cluster/get_settings.asciidoc[] include::cluster/health.asciidoc[] == Ingest APIs diff --git a/docs/reference/cluster.asciidoc b/docs/reference/cluster.asciidoc index 58e36d0e679..f093b6ebcfa 100644 --- a/docs/reference/cluster.asciidoc +++ b/docs/reference/cluster.asciidoc @@ -42,6 +42,8 @@ include::cluster/reroute.asciidoc[] include::cluster/update-settings.asciidoc[] +include::cluster/get-settings.asciidoc[] + include::cluster/nodes-stats.asciidoc[] include::cluster/nodes-info.asciidoc[] diff --git a/docs/reference/cluster/get-settings.asciidoc b/docs/reference/cluster/get-settings.asciidoc new file mode 100644 index 00000000000..b6ea5db1f6d --- /dev/null +++ b/docs/reference/cluster/get-settings.asciidoc @@ -0,0 +1,20 @@ +[[cluster-get-settings]] +== Cluster Get Settings + +The cluster get settings API allows to retrieve the cluster wide settings. + +[source,js] +-------------------------------------------------- +GET /_cluster/settings +-------------------------------------------------- +// CONSOLE + +Or +[source,js] +-------------------------------------------------- +GET /_cluster/settings?include_defaults=true +-------------------------------------------------- +// CONSOLE + +In the second example above, the parameter `include_defaults` ensures that the settings which were not set explicitly +are also returned. By default `include_defaults` is set to false. \ No newline at end of file diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsRequest.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsRequest.java new file mode 100644 index 00000000000..7048b60fc2a --- /dev/null +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsRequest.java @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.action.admin.cluster.settings; + +import org.elasticsearch.action.ActionRequestValidationException; +import org.elasticsearch.action.support.master.MasterNodeReadRequest; + +/** + * This request is specific to the REST client. {@link org.elasticsearch.action.admin.cluster.state.ClusterStateRequest} + * is used on the transport layer. + */ +public class ClusterGetSettingsRequest extends MasterNodeReadRequest { + private boolean includeDefaults = false; + + @Override + public ActionRequestValidationException validate() { + return null; + } + + /** + * When include_defaults is set, return default settings which are normally suppressed. + */ + public ClusterGetSettingsRequest includeDefaults(boolean includeDefaults) { + this.includeDefaults = includeDefaults; + return this; + } + + public boolean includeDefaults() { + return includeDefaults; + } +} diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsResponse.java new file mode 100644 index 00000000000..19b0517d96c --- /dev/null +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsResponse.java @@ -0,0 +1,165 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.action.admin.cluster.settings; + +import org.elasticsearch.action.ActionResponse; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.io.IOException; +import java.util.Objects; + +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; + +/** + * This response is specific to the REST client. {@link org.elasticsearch.action.admin.cluster.state.ClusterStateResponse} + * is used on the transport layer. + */ +public class ClusterGetSettingsResponse extends ActionResponse implements ToXContentObject { + + private Settings persistentSettings = Settings.EMPTY; + private Settings transientSettings = Settings.EMPTY; + private Settings defaultSettings = Settings.EMPTY; + + static final String PERSISTENT_FIELD = "persistent"; + static final String TRANSIENT_FIELD = "transient"; + static final String DEFAULTS_FIELD = "defaults"; + + @SuppressWarnings("unchecked") + private static final ConstructingObjectParser PARSER = + new ConstructingObjectParser<>( + "cluster_get_settings_response", + true, + a -> { + Settings defaultSettings = a[2] == null ? Settings.EMPTY : (Settings) a[2]; + return new ClusterGetSettingsResponse((Settings) a[0], (Settings) a[1], defaultSettings); + } + ); + static { + PARSER.declareObject(constructorArg(), (p, c) -> Settings.fromXContent(p), new ParseField(PERSISTENT_FIELD)); + PARSER.declareObject(constructorArg(), (p, c) -> Settings.fromXContent(p), new ParseField(TRANSIENT_FIELD)); + PARSER.declareObject(optionalConstructorArg(), (p, c) -> Settings.fromXContent(p), new ParseField(DEFAULTS_FIELD)); + } + + public ClusterGetSettingsResponse(Settings persistentSettings, Settings transientSettings, Settings defaultSettings) { + if (persistentSettings != null) { + this.persistentSettings = persistentSettings; + } + if (transientSettings != null) { + this.transientSettings = transientSettings; + } + if (defaultSettings != null) { + this.defaultSettings = defaultSettings; + } + } + + /** + * Returns the persistent settings for the cluster + * @return Settings + */ + public Settings getPersistentSettings() { + return persistentSettings; + } + + /** + * Returns the transient settings for the cluster + * @return Settings + */ + public Settings getTransientSettings() { + return transientSettings; + } + + /** + * Returns the default settings for the cluster (only if {@code include_defaults} was set to true in the request) + * @return Settings + */ + public Settings getDefaultSettings() { + return defaultSettings; + } + + /** + * Returns the string value of the setting for the specified index. The order of search is first + * in persistent settings the transient settings and finally the default settings. + * @param setting the name of the setting to get + * @return String + */ + public String getSetting(String setting) { + if (persistentSettings.hasValue(setting)) { + return persistentSettings.get(setting); + } else if (transientSettings.hasValue(setting)) { + return transientSettings.get(setting); + } else if (defaultSettings.hasValue(setting)) { + return defaultSettings.get(setting); + } else { + return null; + } + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + + builder.startObject(PERSISTENT_FIELD); + persistentSettings.toXContent(builder, params); + builder.endObject(); + + builder.startObject(TRANSIENT_FIELD); + transientSettings.toXContent(builder, params); + builder.endObject(); + + if (defaultSettings.isEmpty() == false) { + builder.startObject(DEFAULTS_FIELD); + defaultSettings.toXContent(builder, params); + builder.endObject(); + } + builder.endObject(); + return builder; + } + + public static ClusterGetSettingsResponse fromXContent(XContentParser parser) { + return PARSER.apply(parser, null); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ClusterGetSettingsResponse that = (ClusterGetSettingsResponse) o; + return Objects.equals(transientSettings, that.transientSettings) && + Objects.equals(persistentSettings, that.persistentSettings) && + Objects.equals(defaultSettings, that.defaultSettings); + } + + @Override + public int hashCode() { + return Objects.hash(transientSettings, persistentSettings, defaultSettings); + } + + @Override + public String toString() { + return Strings.toString(this); + } +} diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterGetSettingsAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterGetSettingsAction.java index f9716d8d1ba..b452b62eb5e 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterGetSettingsAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterGetSettingsAction.java @@ -19,6 +19,7 @@ package org.elasticsearch.rest.action.admin.cluster; +import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse; import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest; import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse; import org.elasticsearch.client.Requests; @@ -65,6 +66,7 @@ public class RestClusterGetSettingsAction extends BaseRestHandler { .nodes(false); final boolean renderDefaults = request.paramAsBoolean("include_defaults", false); clusterStateRequest.local(request.paramAsBoolean("local", clusterStateRequest.local())); + clusterStateRequest.masterNodeTimeout(request.paramAsTime("master_timeout", clusterStateRequest.masterNodeTimeout())); return channel -> client.admin().cluster().state(clusterStateRequest, new RestBuilderListener(channel) { @Override public RestResponse buildResponse(ClusterStateResponse response, XContentBuilder builder) throws Exception { @@ -85,23 +87,13 @@ public class RestClusterGetSettingsAction extends BaseRestHandler { private XContentBuilder renderResponse(ClusterState state, boolean renderDefaults, XContentBuilder builder, ToXContent.Params params) throws IOException { - builder.startObject(); - - builder.startObject("persistent"); - state.metaData().persistentSettings().toXContent(builder, params); - builder.endObject(); - - builder.startObject("transient"); - state.metaData().transientSettings().toXContent(builder, params); - builder.endObject(); - - if (renderDefaults) { - builder.startObject("defaults"); - settingsFilter.filter(clusterSettings.diff(state.metaData().settings(), this.settings)).toXContent(builder, params); - builder.endObject(); - } - - builder.endObject(); - return builder; + return + new ClusterGetSettingsResponse( + state.metaData().persistentSettings(), + state.metaData().transientSettings(), + renderDefaults ? + settingsFilter.filter(clusterSettings.diff(state.metaData().settings(), this.settings)) : + Settings.EMPTY + ).toXContent(builder, params); } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsResponseTests.java new file mode 100644 index 00000000000..1b307e0713c --- /dev/null +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/settings/ClusterGetSettingsResponseTests.java @@ -0,0 +1,57 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.action.admin.cluster.settings; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; +import java.util.function.Predicate; + +public class ClusterGetSettingsResponseTests extends AbstractXContentTestCase { + + @Override + protected ClusterGetSettingsResponse doParseInstance(XContentParser parser) throws IOException { + return ClusterGetSettingsResponse.fromXContent(parser); + } + + @Override + protected boolean supportsUnknownFields() { + return true; + } + + @Override + protected ClusterGetSettingsResponse createTestInstance() { + Settings persistentSettings = ClusterUpdateSettingsResponseTests.randomClusterSettings(0, 2); + Settings transientSettings = ClusterUpdateSettingsResponseTests.randomClusterSettings(0, 2); + Settings defaultSettings = randomBoolean() ? + ClusterUpdateSettingsResponseTests.randomClusterSettings(0, 2): Settings.EMPTY; + return new ClusterGetSettingsResponse(persistentSettings, transientSettings, defaultSettings); + } + + @Override + protected Predicate getRandomFieldsExcludeFilter() { + return p -> + p.startsWith(ClusterGetSettingsResponse.TRANSIENT_FIELD) || + p.startsWith(ClusterGetSettingsResponse.PERSISTENT_FIELD) || + p.startsWith(ClusterGetSettingsResponse.DEFAULTS_FIELD); + } +}