Add dynamic settings validation

Fixes #2749
This commit is contained in:
Igor Motov 2013-03-12 14:41:00 -04:00
parent c008c59927
commit 3a534c64e5
7 changed files with 263 additions and 80 deletions

View File

@ -95,8 +95,13 @@ public class TransportClusterUpdateSettingsAction extends TransportMasterNodeOpe
transientSettings.put(currentState.metaData().transientSettings());
for (Map.Entry<String, String> entry : request.transientSettings().getAsMap().entrySet()) {
if (dynamicSettings.hasDynamicSetting(entry.getKey()) || entry.getKey().startsWith("logger.")) {
transientSettings.put(entry.getKey(), entry.getValue());
changed = true;
String error = dynamicSettings.validateDynamicSetting(entry.getKey(), entry.getValue());
if (error == null) {
transientSettings.put(entry.getKey(), entry.getValue());
changed = true;
} else {
logger.warn("ignoring transient setting [{}], [{}]", entry.getKey(), error);
}
} else {
logger.warn("ignoring transient setting [{}], not dynamically updateable", entry.getKey());
}
@ -106,8 +111,13 @@ public class TransportClusterUpdateSettingsAction extends TransportMasterNodeOpe
persistentSettings.put(currentState.metaData().persistentSettings());
for (Map.Entry<String, String> entry : request.persistentSettings().getAsMap().entrySet()) {
if (dynamicSettings.hasDynamicSetting(entry.getKey()) || entry.getKey().startsWith("logger.")) {
changed = true;
persistentSettings.put(entry.getKey(), entry.getValue());
String error = dynamicSettings.validateDynamicSetting(entry.getKey(), entry.getValue());
if (error == null) {
persistentSettings.put(entry.getKey(), entry.getValue());
changed = true;
} else {
logger.warn("ignoring persistent setting [{}], [{}]", entry.getKey(), error);
}
} else {
logger.warn("ignoring persistent setting [{}], not dynamically updateable", entry.getKey());
}

View File

@ -143,11 +143,23 @@ public class MetaDataUpdateSettingsService extends AbstractComponent implements
final Settings closeSettings = updatedSettingsBuilder.build();
final Set<String> removedSettings = Sets.newHashSet();
for (String key : updatedSettingsBuilder.internalMap().keySet()) {
if (!dynamicSettings.hasDynamicSetting(key)) {
removedSettings.add(key);
final Set<String> errors = Sets.newHashSet();
for (Map.Entry<String, String> setting : updatedSettingsBuilder.internalMap().entrySet()) {
if (!dynamicSettings.hasDynamicSetting(setting.getKey())) {
removedSettings.add(setting.getKey());
} else {
String error = dynamicSettings.validateDynamicSetting(setting.getKey(), setting.getValue());
if (error != null) {
errors.add("[" + setting.getKey() + "] - " + error);
}
}
}
if (!errors.isEmpty()) {
listener.onFailure(new ElasticSearchIllegalArgumentException("can't process the settings: " + errors.toString()));
return;
}
if (!removedSettings.isEmpty()) {
for (String removedSetting : removedSettings) {
updatedSettingsBuilder.remove(removedSetting);

View File

@ -71,10 +71,15 @@ public class ClusterDynamicSettingsModule extends AbstractModule {
);
}
public void addDynamicSetting(String... settings) {
public void addDynamicSettings(String... settings) {
clusterDynamicSettings.addDynamicSettings(settings);
}
public void addDynamicSetting(String setting, Validator validator) {
clusterDynamicSettings.addDynamicSetting(setting, validator);
}
@Override
protected void configure() {
bind(DynamicSettings.class).annotatedWith(ClusterDynamicSettings.class).toInstance(clusterDynamicSettings);

View File

@ -19,20 +19,20 @@
package org.elasticsearch.cluster.settings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableMap;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.regex.Regex;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
/**
*/
public class DynamicSettings {
private ImmutableSet<String> dynamicSettings = ImmutableSet.of();
private ImmutableMap<String, Validator> dynamicSettings = ImmutableMap.of();
public boolean hasDynamicSetting(String key) {
for (String dynamicSetting : dynamicSettings) {
for (String dynamicSetting : dynamicSettings.keySet()) {
if (Regex.simpleMatch(dynamicSetting, key)) {
return true;
}
@ -40,10 +40,32 @@ public class DynamicSettings {
return false;
}
public String validateDynamicSetting(String dynamicSetting, String value) {
for (Map.Entry<String, Validator> setting : dynamicSettings.entrySet()) {
if (Regex.simpleMatch(dynamicSetting, setting.getKey())) {
return setting.getValue().validate(dynamicSetting, value);
}
}
return null;
}
public synchronized void addDynamicSetting(String setting, Validator validator) {
MapBuilder<String, Validator> updatedSettings = MapBuilder.newMapBuilder(dynamicSettings);
updatedSettings.put(setting, validator);
dynamicSettings = updatedSettings.immutableMap();
}
public synchronized void addDynamicSetting(String setting) {
addDynamicSetting(setting, Validator.EmptyValidator.INSTANCE);
}
public synchronized void addDynamicSettings(String... settings) {
HashSet<String> updatedSettings = new HashSet<String>(dynamicSettings);
updatedSettings.addAll(Arrays.asList(settings));
dynamicSettings = ImmutableSet.copyOf(updatedSettings);
MapBuilder<String, Validator> updatedSettings = MapBuilder.newMapBuilder(dynamicSettings);
for (String setting : settings) {
updatedSettings.put(setting, Validator.EmptyValidator.INSTANCE);
}
dynamicSettings = updatedSettings.immutableMap();
}
}

View File

@ -0,0 +1,64 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.cluster.settings;
import org.elasticsearch.ElasticSearchParseException;
import org.elasticsearch.common.unit.TimeValue;
/**
*/
public interface Validator {
String validate(String setting, String value);
public static class EmptyValidator implements Validator {
public static final EmptyValidator INSTANCE = new EmptyValidator();
private EmptyValidator() {
}
@Override
public String validate(String setting, String value) {
return null;
}
}
public static class TimeValueValidator implements Validator {
public static final TimeValueValidator INSTANCE = new TimeValueValidator();
private TimeValueValidator() {
}
@Override
public String validate(String setting, String value) {
try {
if (TimeValue.parseTimeValue(value, null) == null) {
return "cannot parse value [" + value + "] as time";
}
} catch (ElasticSearchParseException ex) {
return "cannot parse value [" + value + "] as time";
}
return null;
}
}
}

View File

@ -23,6 +23,7 @@ import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.routing.allocation.decider.FilterAllocationDecider;
import org.elasticsearch.cluster.routing.allocation.decider.ShardsLimitAllocationDecider;
import org.elasticsearch.cluster.settings.DynamicSettings;
import org.elasticsearch.cluster.settings.Validator;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.gateway.local.LocalGatewayAllocator;
import org.elasticsearch.index.engine.robin.RobinEngine;
@ -46,75 +47,78 @@ public class IndexDynamicSettingsModule extends AbstractModule {
public IndexDynamicSettingsModule() {
indexDynamicSettings = new DynamicSettings();
indexDynamicSettings.addDynamicSettings(
AbstractIndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC,
AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE,
FilterAllocationDecider.INDEX_ROUTING_REQUIRE_GROUP + "*",
FilterAllocationDecider.INDEX_ROUTING_INCLUDE_GROUP + "*",
FilterAllocationDecider.INDEX_ROUTING_EXCLUDE_GROUP + "*",
FsTranslog.INDEX_TRANSLOG_FS_TYPE,
FsTranslog.INDEX_TRANSLOG_FS_BUFFER_SIZE,
FsTranslog.INDEX_TRANSLOG_FS_TRANSIENT_BUFFER_SIZE,
IndexMetaData.SETTING_NUMBER_OF_REPLICAS,
IndexMetaData.SETTING_AUTO_EXPAND_REPLICAS,
IndexMetaData.SETTING_READ_ONLY,
IndexMetaData.SETTING_BLOCKS_READ,
IndexMetaData.SETTING_BLOCKS_WRITE,
IndexMetaData.SETTING_BLOCKS_METADATA,
IndexShardGatewayService.INDEX_GATEWAY_SNAPSHOT_INTERVAL,
IndicesTTLService.INDEX_TTL_DISABLE_PURGE,
InternalIndexShard.INDEX_REFRESH_INTERVAL,
LocalGatewayAllocator.INDEX_RECOVERY_INITIAL_SHARDS,
LogByteSizeMergePolicyProvider.INDEX_MERGE_POLICY_MIN_MERGE_SIZE,
LogByteSizeMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_SIZE,
LogByteSizeMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_DOCS,
LogByteSizeMergePolicyProvider.INDEX_MERGE_POLICY_MERGE_FACTOR,
LogByteSizeMergePolicyProvider.INDEX_COMPOUND_FORMAT,
LogDocMergePolicyProvider.INDEX_MERGE_POLICY_MIN_MERGE_DOCS,
LogDocMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_DOCS,
LogDocMergePolicyProvider.INDEX_MERGE_POLICY_MERGE_FACTOR,
LogDocMergePolicyProvider.INDEX_COMPOUND_FORMAT,
RobinEngine.INDEX_TERM_INDEX_INTERVAL,
RobinEngine.INDEX_TERM_INDEX_DIVISOR,
RobinEngine.INDEX_INDEX_CONCURRENCY,
RobinEngine.INDEX_GC_DELETES,
RobinEngine.INDEX_CODEC,
RobinEngine.INDEX_FAIL_ON_MERGE_FAILURE,
ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_THRESHOLD_INDEX_WARN,
ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_THRESHOLD_INDEX_INFO,
ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_THRESHOLD_INDEX_DEBUG,
ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_THRESHOLD_INDEX_TRACE,
ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_REFORMAT,
ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_LEVEL,
ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_QUERY_WARN,
ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_QUERY_INFO,
ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_QUERY_DEBUG,
ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_QUERY_TRACE,
ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_WARN,
ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_INFO,
ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_DEBUG,
ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_TRACE,
ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_REFORMAT,
ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_LEVEL,
ShardsLimitAllocationDecider.INDEX_TOTAL_SHARDS_PER_NODE,
TieredMergePolicyProvider.INDEX_MERGE_POLICY_EXPUNGE_DELETES_ALLOWED,
TieredMergePolicyProvider.INDEX_MERGE_POLICY_FLOOR_SEGMENT,
TieredMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_AT_ONCE,
TieredMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_AT_ONCE_EXPLICIT,
TieredMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGED_SEGMENT,
TieredMergePolicyProvider.INDEX_MERGE_POLICY_SEGMENTS_PER_TIER,
TieredMergePolicyProvider.INDEX_MERGE_POLICY_RECLAIM_DELETES_WEIGHT,
TieredMergePolicyProvider.INDEX_COMPOUND_FORMAT,
TranslogService.INDEX_TRANSLOG_FLUSH_THRESHOLD_OPS,
TranslogService.INDEX_TRANSLOG_FLUSH_THRESHOLD_SIZE,
TranslogService.INDEX_TRANSLOG_FLUSH_THRESHOLD_PERIOD,
TranslogService.INDEX_TRANSLOG_DISABLE_FLUSH);
indexDynamicSettings.addDynamicSetting(AbstractIndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC);
indexDynamicSettings.addDynamicSetting(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE);
indexDynamicSettings.addDynamicSetting(FilterAllocationDecider.INDEX_ROUTING_REQUIRE_GROUP + "*");
indexDynamicSettings.addDynamicSetting(FilterAllocationDecider.INDEX_ROUTING_INCLUDE_GROUP + "*");
indexDynamicSettings.addDynamicSetting(FilterAllocationDecider.INDEX_ROUTING_EXCLUDE_GROUP + "*");
indexDynamicSettings.addDynamicSetting(FsTranslog.INDEX_TRANSLOG_FS_TYPE);
indexDynamicSettings.addDynamicSetting(FsTranslog.INDEX_TRANSLOG_FS_BUFFER_SIZE);
indexDynamicSettings.addDynamicSetting(FsTranslog.INDEX_TRANSLOG_FS_TRANSIENT_BUFFER_SIZE);
indexDynamicSettings.addDynamicSetting(IndexMetaData.SETTING_NUMBER_OF_REPLICAS);
indexDynamicSettings.addDynamicSetting(IndexMetaData.SETTING_AUTO_EXPAND_REPLICAS);
indexDynamicSettings.addDynamicSetting(IndexMetaData.SETTING_READ_ONLY);
indexDynamicSettings.addDynamicSetting(IndexMetaData.SETTING_BLOCKS_READ);
indexDynamicSettings.addDynamicSetting(IndexMetaData.SETTING_BLOCKS_WRITE);
indexDynamicSettings.addDynamicSetting(IndexMetaData.SETTING_BLOCKS_METADATA);
indexDynamicSettings.addDynamicSetting(IndexShardGatewayService.INDEX_GATEWAY_SNAPSHOT_INTERVAL);
indexDynamicSettings.addDynamicSetting(IndicesTTLService.INDEX_TTL_DISABLE_PURGE);
indexDynamicSettings.addDynamicSetting(InternalIndexShard.INDEX_REFRESH_INTERVAL, Validator.TimeValueValidator.INSTANCE);
indexDynamicSettings.addDynamicSetting(LocalGatewayAllocator.INDEX_RECOVERY_INITIAL_SHARDS);
indexDynamicSettings.addDynamicSetting(LogByteSizeMergePolicyProvider.INDEX_MERGE_POLICY_MIN_MERGE_SIZE);
indexDynamicSettings.addDynamicSetting(LogByteSizeMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_SIZE);
indexDynamicSettings.addDynamicSetting(LogByteSizeMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_DOCS);
indexDynamicSettings.addDynamicSetting(LogByteSizeMergePolicyProvider.INDEX_MERGE_POLICY_MERGE_FACTOR);
indexDynamicSettings.addDynamicSetting(LogByteSizeMergePolicyProvider.INDEX_COMPOUND_FORMAT);
indexDynamicSettings.addDynamicSetting(LogDocMergePolicyProvider.INDEX_MERGE_POLICY_MIN_MERGE_DOCS);
indexDynamicSettings.addDynamicSetting(LogDocMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_DOCS);
indexDynamicSettings.addDynamicSetting(LogDocMergePolicyProvider.INDEX_MERGE_POLICY_MERGE_FACTOR);
indexDynamicSettings.addDynamicSetting(LogDocMergePolicyProvider.INDEX_COMPOUND_FORMAT);
indexDynamicSettings.addDynamicSetting(RobinEngine.INDEX_TERM_INDEX_INTERVAL);
indexDynamicSettings.addDynamicSetting(RobinEngine.INDEX_TERM_INDEX_DIVISOR);
indexDynamicSettings.addDynamicSetting(RobinEngine.INDEX_INDEX_CONCURRENCY);
indexDynamicSettings.addDynamicSetting(RobinEngine.INDEX_GC_DELETES);
indexDynamicSettings.addDynamicSetting(RobinEngine.INDEX_CODEC);
indexDynamicSettings.addDynamicSetting(RobinEngine.INDEX_FAIL_ON_MERGE_FAILURE);
indexDynamicSettings.addDynamicSetting(ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_THRESHOLD_INDEX_WARN);
indexDynamicSettings.addDynamicSetting(ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_THRESHOLD_INDEX_INFO);
indexDynamicSettings.addDynamicSetting(ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_THRESHOLD_INDEX_DEBUG);
indexDynamicSettings.addDynamicSetting(ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_THRESHOLD_INDEX_TRACE);
indexDynamicSettings.addDynamicSetting(ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_REFORMAT);
indexDynamicSettings.addDynamicSetting(ShardSlowLogIndexingService.INDEX_INDEXING_SLOWLOG_LEVEL);
indexDynamicSettings.addDynamicSetting(ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_QUERY_WARN);
indexDynamicSettings.addDynamicSetting(ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_QUERY_INFO);
indexDynamicSettings.addDynamicSetting(ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_QUERY_DEBUG);
indexDynamicSettings.addDynamicSetting(ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_QUERY_TRACE);
indexDynamicSettings.addDynamicSetting(ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_WARN);
indexDynamicSettings.addDynamicSetting(ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_INFO);
indexDynamicSettings.addDynamicSetting(ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_DEBUG);
indexDynamicSettings.addDynamicSetting(ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_TRACE);
indexDynamicSettings.addDynamicSetting(ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_REFORMAT);
indexDynamicSettings.addDynamicSetting(ShardSlowLogSearchService.INDEX_SEARCH_SLOWLOG_LEVEL);
indexDynamicSettings.addDynamicSetting(ShardsLimitAllocationDecider.INDEX_TOTAL_SHARDS_PER_NODE);
indexDynamicSettings.addDynamicSetting(TieredMergePolicyProvider.INDEX_MERGE_POLICY_EXPUNGE_DELETES_ALLOWED);
indexDynamicSettings.addDynamicSetting(TieredMergePolicyProvider.INDEX_MERGE_POLICY_FLOOR_SEGMENT);
indexDynamicSettings.addDynamicSetting(TieredMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_AT_ONCE);
indexDynamicSettings.addDynamicSetting(TieredMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_AT_ONCE_EXPLICIT);
indexDynamicSettings.addDynamicSetting(TieredMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGED_SEGMENT);
indexDynamicSettings.addDynamicSetting(TieredMergePolicyProvider.INDEX_MERGE_POLICY_SEGMENTS_PER_TIER);
indexDynamicSettings.addDynamicSetting(TieredMergePolicyProvider.INDEX_MERGE_POLICY_RECLAIM_DELETES_WEIGHT);
indexDynamicSettings.addDynamicSetting(TieredMergePolicyProvider.INDEX_COMPOUND_FORMAT);
indexDynamicSettings.addDynamicSetting(TranslogService.INDEX_TRANSLOG_FLUSH_THRESHOLD_OPS);
indexDynamicSettings.addDynamicSetting(TranslogService.INDEX_TRANSLOG_FLUSH_THRESHOLD_SIZE);
indexDynamicSettings.addDynamicSetting(TranslogService.INDEX_TRANSLOG_FLUSH_THRESHOLD_PERIOD);
indexDynamicSettings.addDynamicSetting(TranslogService.INDEX_TRANSLOG_DISABLE_FLUSH);
}
public void addDynamicSetting(String... settings) {
public void addDynamicSettings(String... settings) {
indexDynamicSettings.addDynamicSettings(settings);
}
public void addDynamicSetting(String setting, Validator validator) {
indexDynamicSettings.addDynamicSetting(setting, validator);
}
@Override
protected void configure() {
bind(DynamicSettings.class).annotatedWith(IndexDynamicSettings.class).toInstance(indexDynamicSettings);

View File

@ -0,0 +1,66 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.test.integration.cluster;
import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.common.Priority;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
/**
*/
public class UpdateSettingsValidationTests extends AbstractNodesTests {
@AfterMethod
public void closeNodes() {
closeAllNodes();
}
@Test
public void testUpdateSettingsValidation() throws Exception {
startNode("master", settingsBuilder().put("node.data", false).build());
startNode("node1", settingsBuilder().put("node.master", false).build());
startNode("node2", settingsBuilder().put("node.master", false).build());
client("master").admin().indices().prepareCreate("test")
.setSettings(settingsBuilder().put("index.number_of_shards", 5).put("index.number_of_replicas", 1)).execute().actionGet();
ClusterHealthResponse healthResponse = client("master").admin().cluster().prepareHealth("test").setWaitForEvents(Priority.LANGUID).setWaitForNodes("3").setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
assertThat(healthResponse.getIndices().get("test").getActiveShards(), equalTo(10));
client("master").admin().indices().prepareUpdateSettings("test").setSettings(settingsBuilder().put("index.number_of_replicas", 0)).execute().actionGet();
healthResponse = client("master").admin().cluster().prepareHealth("test").setWaitForEvents(Priority.LANGUID).setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
assertThat(healthResponse.getIndices().get("test").getActiveShards(), equalTo(5));
try {
client("master").admin().indices().prepareUpdateSettings("test").setSettings(settingsBuilder().put("index.refresh_interval", "")).execute().actionGet();
assert false;
} catch (ElasticSearchIllegalArgumentException ex) {
logger.info("Error message: [{}]", ex.getMessage());
}
}
}