diff --git a/docs/user/admin/settings.rst b/docs/user/admin/settings.rst index 9808a4eb2e..89d93e1fb5 100644 --- a/docs/user/admin/settings.rst +++ b/docs/user/admin/settings.rst @@ -37,7 +37,7 @@ You can update the setting with a new value like this. SQL query:: - >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_cluster/settings -d '{ + >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_opendistro/_sql/settings -d '{ "transient" : { "opendistro.sql.enabled" : "false" } @@ -99,7 +99,7 @@ You can update the setting with a new value like this. SQL query:: - >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_cluster/settings -d '{ + >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_opendistro/_sql/settings -d '{ "transient" : { "opendistro.sql.query.slowlog" : "10" } @@ -141,7 +141,7 @@ You can update the setting with a new value like this. SQL query:: - >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_cluster/settings -d '{ + >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_opendistro/_sql/settings -d '{ "transient" : { "opendistro.sql.query.analysis.enabled" : "false" } @@ -185,7 +185,7 @@ You can update the setting with a new value like this. SQL query:: - >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_cluster/settings -d '{ + >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_opendistro/_sql/settings -d '{ "transient" : { "opendistro.sql.query.analysis.semantic.suggestion" : "true" } @@ -253,7 +253,7 @@ You can update the setting with a new value like this. SQL query:: - >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_cluster/settings -d '{ + >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_opendistro/_sql/settings -d '{ "transient" : { "opendistro.sql.query.analysis.semantic.threshold" : "50" } @@ -299,7 +299,7 @@ You can update the setting with a new value like this. SQL query:: - >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_cluster/settings -d '{ + >> curl -H 'Content-Type: application/json' -X PUT localhost:9200/_opendistro/_sql/settings -d '{ "transient" : { "opendistro.sql.query.response.format" : "json" } diff --git a/src/main/java/com/amazon/opendistroforelasticsearch/sql/plugin/RestSqlSettingsAction.java b/src/main/java/com/amazon/opendistroforelasticsearch/sql/plugin/RestSqlSettingsAction.java new file mode 100644 index 0000000000..5a977ac729 --- /dev/null +++ b/src/main/java/com/amazon/opendistroforelasticsearch/sql/plugin/RestSqlSettingsAction.java @@ -0,0 +1,125 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazon.opendistroforelasticsearch.sql.plugin; + +import com.amazon.opendistroforelasticsearch.sql.executor.format.ErrorMessageFactory; + +import com.amazon.opendistroforelasticsearch.sql.utils.LogUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.elasticsearch.ElasticsearchGenerationException; +import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; +import org.elasticsearch.client.Requests; +import org.elasticsearch.client.node.NodeClient; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.rest.BaseRestHandler; +import org.elasticsearch.rest.BytesRestResponse; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.action.RestToXContentListener; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.elasticsearch.rest.RestStatus.INTERNAL_SERVER_ERROR; + +/** + * Interface to manage opendistro.sql.* cluster settings + * All non-sql settings are ignored. + * Any non-transient and non-persistent settings are ignored. + */ +public class RestSqlSettingsAction extends BaseRestHandler { + private static final Logger LOG = LogManager.getLogger(RestSqlSettingsAction.class); + + private static final String PERSISTENT = "persistent"; + private static final String TRANSIENT = "transient"; + private static final String SQL_SETTINGS_PREFIX = "opendistro.sql."; + + /** + * API endpoint path + */ + public static final String SETTINGS_API_ENDPOINT = "/_opendistro/_sql/settings"; + + public RestSqlSettingsAction(Settings settings, RestController restController) { + super(); + restController.registerHandler(RestRequest.Method.PUT, SETTINGS_API_ENDPOINT, this); + } + + @Override + public String getName() { + return "sql_settings_action"; + } + + /** + * @see org.elasticsearch.rest.action.admin.cluster.RestClusterUpdateSettingsAction + */ + @Override + protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { + LogUtils.addRequestId(); + final ClusterUpdateSettingsRequest clusterUpdateSettingsRequest = Requests.clusterUpdateSettingsRequest(); + clusterUpdateSettingsRequest.timeout(request.paramAsTime("timeout", clusterUpdateSettingsRequest.timeout())); + clusterUpdateSettingsRequest.masterNodeTimeout( + request.paramAsTime("master_timeout", clusterUpdateSettingsRequest.masterNodeTimeout())); + Map source; + try (XContentParser parser = request.contentParser()) { + source = parser.map(); + } + + try { + if (source.containsKey(TRANSIENT)) { + clusterUpdateSettingsRequest.transientSettings(getAndFilterSettings((Map) source.get(TRANSIENT))); + } + if (source.containsKey(PERSISTENT)) { + clusterUpdateSettingsRequest.persistentSettings(getAndFilterSettings((Map) source.get(PERSISTENT))); + } + + return channel -> client.admin().cluster().updateSettings( + clusterUpdateSettingsRequest, new RestToXContentListener<>(channel)); + } catch (Exception e) { + LOG.error("Error changing OpenDistro SQL plugin cluster settings", e); + return channel -> channel.sendResponse(new BytesRestResponse(INTERNAL_SERVER_ERROR, + ErrorMessageFactory.createErrorMessage(e, INTERNAL_SERVER_ERROR.getStatus()).toString())); + } + } + + @Override + protected Set responseParams() { + Set responseParams = new HashSet<>(super.responseParams()); + responseParams.addAll(Arrays.asList("sql", "flat", "separator", "_score", "_type", "_id", "newLine", "format")); + return responseParams; + } + + private Settings getAndFilterSettings(Map source) { + try { + XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); + builder.map(source); + Settings.Builder settingsBuilder = Settings.builder(). + loadFromSource(Strings.toString(builder), builder.contentType()); + settingsBuilder.keys().removeIf(key -> !key.startsWith(SQL_SETTINGS_PREFIX)); + return settingsBuilder.build(); + } catch (IOException e) { + throw new ElasticsearchGenerationException("Failed to generate [" + source + "]", e); + } + } +} diff --git a/src/main/java/com/amazon/opendistroforelasticsearch/sql/plugin/SqlPlug.java b/src/main/java/com/amazon/opendistroforelasticsearch/sql/plugin/SqlPlug.java index 670bae785a..a241de596f 100644 --- a/src/main/java/com/amazon/opendistroforelasticsearch/sql/plugin/SqlPlug.java +++ b/src/main/java/com/amazon/opendistroforelasticsearch/sql/plugin/SqlPlug.java @@ -78,7 +78,8 @@ public List getRestHandlers(Settings settings, RestController restC Metrics.getInstance().registerDefaultMetrics(); return Arrays.asList( new RestSqlAction(settings, restController), - new RestSqlStatsAction(settings, restController)); + new RestSqlStatsAction(settings, restController), + new RestSqlSettingsAction(settings, restController)); } @Override diff --git a/src/test/java/com/amazon/opendistroforelasticsearch/sql/doctest/core/builder/DocBuilder.java b/src/test/java/com/amazon/opendistroforelasticsearch/sql/doctest/core/builder/DocBuilder.java index 811fc46024..ea26a3bcd0 100644 --- a/src/test/java/com/amazon/opendistroforelasticsearch/sql/doctest/core/builder/DocBuilder.java +++ b/src/test/java/com/amazon/opendistroforelasticsearch/sql/doctest/core/builder/DocBuilder.java @@ -193,7 +193,7 @@ default Requests put(String name, Object value) { StringUtils.format("\"%s\": {\"%s\": \"%s\"}", "transient", name, value); return new Requests( restClient(), - new SqlRequest("PUT", "/_cluster/settings", new Body(setting).toString()), + new SqlRequest("PUT", "/_opendistro/_sql/settings", new Body(setting).toString()), null ); } diff --git a/src/test/java/com/amazon/opendistroforelasticsearch/sql/esintgtest/PluginIT.java b/src/test/java/com/amazon/opendistroforelasticsearch/sql/esintgtest/PluginIT.java index e258decea8..93d9fe305c 100644 --- a/src/test/java/com/amazon/opendistroforelasticsearch/sql/esintgtest/PluginIT.java +++ b/src/test/java/com/amazon/opendistroforelasticsearch/sql/esintgtest/PluginIT.java @@ -15,15 +15,17 @@ package com.amazon.opendistroforelasticsearch.sql.esintgtest; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.Response; import org.elasticsearch.client.ResponseException; import org.json.JSONObject; -import org.junit.Assert; import org.junit.Test; import java.io.IOException; import java.util.Locale; +import static com.amazon.opendistroforelasticsearch.sql.esintgtest.TestUtils.getResponseBody; import static com.amazon.opendistroforelasticsearch.sql.esintgtest.TestsConstants.TEST_INDEX_ACCOUNT; import static org.hamcrest.Matchers.equalTo; @@ -33,15 +35,16 @@ public class PluginIT extends SQLIntegTestCase { @Override protected void init() throws Exception { - loadIndex(Index.ACCOUNT); + wipeAllClusterSettings(); } @Test public void sqlEnableSettingsTest() throws IOException { + loadIndex(Index.ACCOUNT); updateClusterSettings(new ClusterSetting(PERSISTENT, "opendistro.sql.enabled", "true")); String query = String.format(Locale.ROOT, "SELECT firstname FROM %s WHERE account_number=1", TEST_INDEX_ACCOUNT); JSONObject queryResult = executeQuery(query); - Assert.assertThat(getHits(queryResult).length(), equalTo(1)); + assertThat(getHits(queryResult).length(), equalTo(1)); updateClusterSettings(new ClusterSetting(PERSISTENT, "opendistro.sql.enabled", "false")); Response response = null; @@ -52,22 +55,399 @@ public void sqlEnableSettingsTest() throws IOException { } queryResult = new JSONObject(TestUtils.getResponseBody(response)); - Assert.assertThat(queryResult.getInt("status"), equalTo(400)); + assertThat(queryResult.getInt("status"), equalTo(400)); JSONObject error = queryResult.getJSONObject("error"); - Assert.assertThat(error.getString("reason"), equalTo("Invalid SQL query")); - Assert.assertThat(error.getString("details"), equalTo("Either opendistro.sql.enabled or rest.action.multi.allow_explicit_index setting is false")); - Assert.assertThat(error.getString("type"), equalTo("SQLFeatureDisabledException")); - resetClusterSettings(PERSISTENT, "opendistro.sql.enabled"); + assertThat(error.getString("reason"), equalTo("Invalid SQL query")); + assertThat(error.getString("details"), equalTo("Either opendistro.sql.enabled or rest.action.multi.allow_explicit_index setting is false")); + assertThat(error.getString("type"), equalTo("SQLFeatureDisabledException")); + wipeAllClusterSettings(); + } + + @Test + public void sqlTransientOnlySettingTest() throws IOException { + // (1) compact form + String settings = "{" + + " \"transient\": {" + + " \"opendistro.sql.metrics.rollinginterval\": \"80\"" + + " }" + + "}"; + JSONObject actual = updateViaSQLSettingsAPI(settings); + JSONObject expected = new JSONObject("{" + + " \"acknowledged\" : true," + + " \"persistent\" : { }," + + " \"transient\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics\" : {" + + " \"rollinginterval\" : \"80\"" + + " }" + + " }" + + " }" + + " }" + + "}"); + assertTrue(actual.similar(expected)); + + // (2) partial expanded form + settings = "{" + + " \"transient\": {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics.rollinginterval\": \"75\"" + + " }" + + " }" + + " }" + + "}"; + actual = updateViaSQLSettingsAPI(settings); + expected = new JSONObject("{" + + " \"acknowledged\" : true," + + " \"persistent\" : { }," + + " \"transient\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics\" : {" + + " \"rollinginterval\" : \"75\"" + + " }" + + " }" + + " }" + + " }" + + "}"); + assertTrue(actual.similar(expected)); + + + // (3) full expanded form + settings = "{" + + " \"transient\": {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics\": {" + + " \"rollinginterval\": \"65\"" + + " }" + + " }" + + " }" + + " }" + + "}"; + actual = updateViaSQLSettingsAPI(settings); + expected = new JSONObject("{" + + " \"acknowledged\" : true," + + " \"persistent\" : { }," + + " \"transient\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics\" : {" + + " \"rollinginterval\" : \"65\"" + + " }" + + " }" + + " }" + + " }" + + "}"); + assertTrue(actual.similar(expected)); + } + + @Test + public void sqlPersistentOnlySettingTest() throws IOException { + // (1) compact form + String settings = "{" + + " \"persistent\": {" + + " \"opendistro.sql.metrics.rollinginterval\": \"80\"" + + " }" + + "}"; + JSONObject actual = updateViaSQLSettingsAPI(settings); + JSONObject expected = new JSONObject("{" + + " \"acknowledged\" : true," + + " \"transient\" : { }," + + " \"persistent\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics\" : {" + + " \"rollinginterval\" : \"80\"" + + " }" + + " }" + + " }" + + " }" + + "}"); + assertTrue(actual.similar(expected)); + + // (2) partial expanded form + settings = "{" + + " \"persistent\": {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics.rollinginterval\": \"75\"" + + " }" + + " }" + + " }" + + "}"; + actual = updateViaSQLSettingsAPI(settings); + expected = new JSONObject("{" + + " \"acknowledged\" : true," + + " \"transient\" : { }," + + " \"persistent\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics\" : {" + + " \"rollinginterval\" : \"75\"" + + " }" + + " }" + + " }" + + " }" + + "}"); + assertTrue(actual.similar(expected)); + + + // (3) full expanded form + settings = "{" + + " \"persistent\": {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics\": {" + + " \"rollinginterval\": \"65\"" + + " }" + + " }" + + " }" + + " }" + + "}"; + actual = updateViaSQLSettingsAPI(settings); + expected = new JSONObject("{" + + " \"acknowledged\" : true," + + " \"transient\" : { }," + + " \"persistent\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics\" : {" + + " \"rollinginterval\" : \"65\"" + + " }" + + " }" + + " }" + + " }" + + "}"); + assertTrue(actual.similar(expected)); + } + + /** + * Both transient and persistent settings are applied for same settings. + * This is similiar to _cluster/settings behavior + */ + @Test + public void sqlCombinedSettingTest() throws IOException { + String settings = "{" + + " \"transient\": {" + + " \"opendistro.sql.metrics.rollingwindow\": \"3700\"," + + " \"opendistro.sql.query.analysis.semantic.suggestion\" : \"false\"" + + " }," + + " \"persistent\": {" + + " \"opendistro.sql.query.analysis.semantic.suggestion\" : \"true\"" + + " }" + + "}" ; + JSONObject actual = updateViaSQLSettingsAPI(settings); + JSONObject expected = new JSONObject("{" + + " \"acknowledged\" : true," + + " \"persistent\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"query\" : {" + + " \"analysis\" : {" + + " \"semantic\" : {" + + " \"suggestion\" : \"true\"" + + " }" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"transient\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics\" : {" + + " \"rollingwindow\" : \"3700\"" + + " }," + + " \"query\" : {" + + " \"analysis\" : {" + + " \"semantic\" : {" + + " \"suggestion\" : \"false\"" + + " }" + + " }" + + " }" + + " }" + + " }" + + " }" + + "}"); + assertTrue(actual.similar(expected)); } /** - * We need to reset all the cluster settings, otherwise ESIntegTestCase will throw - * java.lang.AssertionError: test leaves persistent cluster metadata behind - * - * TODO: Look for a way to reset all the persistent and transient settings instead of - * individually resetting of each such setting + * Ignore all non opendistro.sql settings. + * Only settings starting with opendistro.sql. are affected */ - private JSONObject resetClusterSettings(String settingType, String setting) throws IOException { - return updateClusterSettings(new ClusterSetting(settingType, setting, null)); + @Test + public void ignoreNonSQLSettingsTest() throws IOException { + String settings = "{" + + " \"transient\": {" + + " \"opendistro.sql.metrics.rollingwindow\": \"3700\"," + + " \"opendistro.alerting.metrics.rollingwindow\": \"3700\"," + + " \"search.max_buckets\": \"10000\"," + + " \"search.max_keep_alive\": \"24h\"" + + " }," + + " \"persistent\": {" + + " \"opendistro.sql.query.analysis.semantic.suggestion\": \"true\"," + + " \"opendistro.alerting.metrics.rollingwindow\": \"3700\"," + + " \"thread_pool.analyze.queue_size\": \"16\"" + + " }" + + "}" ; + JSONObject actual = updateViaSQLSettingsAPI(settings); + JSONObject expected = new JSONObject("{" + + " \"acknowledged\" : true," + + " \"persistent\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"query\" : {" + + " \"analysis\" : {" + + " \"semantic\" : {" + + " \"suggestion\" : \"true\"" + + " }" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"transient\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"metrics\" : {" + + " \"rollingwindow\" : \"3700\"" + + " }" + + " }" + + " }" + + " }" + + "}"); + assertTrue(actual.similar(expected)); + } + + @Test + public void ignoreNonTransientNonPersistentSettingsTest() throws IOException { + String settings = "{" + + " \"transient\": {" + + " \"opendistro.sql.query.response.format\": \"jdbc\"" + + " }," + + " \"persistent\": {" + + " \"opendistro.sql.query.slowlog\": \"2\"" + + " }," + + " \"hello\": {" + + " \"world\" : {" + + " \"name\" : \"John Doe\"" + + " }" + + " }" + + "}" ; + JSONObject actual = updateViaSQLSettingsAPI(settings); + JSONObject expected = new JSONObject("{" + + " \"acknowledged\" : true," + + " \"persistent\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"query\" : {" + + " \"slowlog\" : \"2\"" + + " }" + + " }" + + " }" + + " }," + + " \"transient\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"query\" : {" + + " \"response\" : {" + + " \"format\" : \"jdbc\"" + + " }" + + " }" + + " }" + + " }" + + " }" + + "}"); + assertTrue(actual.similar(expected)); + } + + @Test + public void sqlCombinedMixedSettingTest() throws IOException { + String settings = "{" + + " \"transient\": {" + + " \"opendistro.sql.query.response.format\": \"json\"" + + " }," + + " \"persistent\": {" + + " \"opendistro\": {" + + " \"sql\": {" + + " \"query\": {" + + " \"slowlog\": \"1\"," + + " \"response.format\": \"jdbc\"" + + " }" + + " }" + + " }" + + " }," + + " \"hello\": {" + + " \"world\": {" + + " \"city\": \"Seattle\"" + + " }" + + " }" + + "}" ; + JSONObject actual = updateViaSQLSettingsAPI(settings); + JSONObject expected = new JSONObject("{" + + " \"acknowledged\" : true," + + " \"persistent\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"query\" : {" + + " \"slowlog\" : \"1\"," + + " \"response\" : {" + + " \"format\" : \"jdbc\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"transient\" : {" + + " \"opendistro\" : {" + + " \"sql\" : {" + + " \"query\" : {" + + " \"response\" : {" + + " \"format\" : \"json\"" + + " }" + + " }" + + " }" + + " }" + + " }" + + "}"); + assertTrue(actual.similar(expected)); + } + + @Test + public void nonRegisteredSQLSettingsThrowException() throws IOException { + String settings = "{" + + " \"transient\": {" + + " \"opendistro.sql.query.state.city\": \"Seattle\"" + + " }" + + "}" ; + + JSONObject actual; + Response response = null; + try { + actual = updateViaSQLSettingsAPI(settings); + } catch (ResponseException ex) { + response = ex.getResponse(); + } + + actual = new JSONObject(TestUtils.getResponseBody(response)); + assertThat(actual.getInt("status"), equalTo(400)); + assertThat(actual.query("/error/type"), equalTo("illegal_argument_exception")); + assertThat( + actual.query("/error/reason"), + equalTo("transient setting [opendistro.sql.query.state.city], not recognized") + ); + } + + protected static JSONObject updateViaSQLSettingsAPI(String body) throws IOException { + Request request = new Request("PUT", "/_opendistro/_sql/settings"); + request.setJsonEntity(body); + RequestOptions.Builder restOptionsBuilder = RequestOptions.DEFAULT.toBuilder(); + restOptionsBuilder.addHeader("Content-Type", "application/json"); + request.setOptions(restOptionsBuilder); + Response response = client().performRequest(request); + return new JSONObject(getResponseBody(response)); } } diff --git a/src/test/java/com/amazon/opendistroforelasticsearch/sql/esintgtest/SQLIntegTestCase.java b/src/test/java/com/amazon/opendistroforelasticsearch/sql/esintgtest/SQLIntegTestCase.java index 19c8081927..fb5b5f777b 100644 --- a/src/test/java/com/amazon/opendistroforelasticsearch/sql/esintgtest/SQLIntegTestCase.java +++ b/src/test/java/com/amazon/opendistroforelasticsearch/sql/esintgtest/SQLIntegTestCase.java @@ -147,7 +147,7 @@ private void increaseScriptMaxCompilationsRate() throws IOException { updateClusterSettings(new ClusterSetting("transient", "script.max_compilations_rate", "10000/1m")); } - private static void wipeAllClusterSettings() throws IOException { + protected static void wipeAllClusterSettings() throws IOException { updateClusterSettings(new ClusterSetting("persistent", "*", null)); updateClusterSettings(new ClusterSetting("transient", "*", null)); }