/* * 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.common.settings; import org.apache.logging.log4j.Level; import org.elasticsearch.Version; 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.common.logging.ESLoggerFactory; import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.index.IndexModule; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.transport.TransportService; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.function.Function; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.startsWith; public class ScopedSettingsTests extends ESTestCase { public void testResetSetting() { Setting<Integer> dynamicSetting = Setting.intSetting("some.dyn.setting", 1, Property.Dynamic, Property.NodeScope); Setting<Integer> staticSetting = Setting.intSetting("some.static.setting", 1, Property.NodeScope); Settings currentSettings = Settings.builder().put("some.dyn.setting", 5).put("some.static.setting", 6).put("archived.foo.bar", 9) .build(); ClusterSettings service = new ClusterSettings(currentSettings , new HashSet<>(Arrays.asList(dynamicSetting, staticSetting))); expectThrows(IllegalArgumentException.class, () -> service.updateDynamicSettings(Settings.builder().put("some.dyn.setting", 8).putNull("some.static.setting").build(), Settings.builder().put(currentSettings), Settings.builder(), "node")); Settings.Builder target = Settings.builder().put(currentSettings); Settings.Builder update = Settings.builder(); assertTrue(service.updateDynamicSettings(Settings.builder().put("some.dyn.setting", 8).build(), target, update, "node")); assertEquals(8, dynamicSetting.get(target.build()).intValue()); assertEquals(6, staticSetting.get(target.build()).intValue()); assertEquals(9, target.build().getAsInt("archived.foo.bar", null).intValue()); target = Settings.builder().put(currentSettings); update = Settings.builder(); assertTrue(service.updateDynamicSettings(Settings.builder().putNull("some.dyn.setting").build(), target, update, "node")); assertEquals(1, dynamicSetting.get(target.build()).intValue()); assertEquals(6, staticSetting.get(target.build()).intValue()); assertEquals(9, target.build().getAsInt("archived.foo.bar", null).intValue()); target = Settings.builder().put(currentSettings); update = Settings.builder(); assertTrue(service.updateDynamicSettings(Settings.builder().putNull("archived.foo.bar").build(), target, update, "node")); assertEquals(5, dynamicSetting.get(target.build()).intValue()); assertEquals(6, staticSetting.get(target.build()).intValue()); assertNull(target.build().getAsInt("archived.foo.bar", null)); target = Settings.builder().put(currentSettings); update = Settings.builder(); assertTrue(service.updateDynamicSettings(Settings.builder().putNull("some.*").build(), target, update, "node")); assertEquals(1, dynamicSetting.get(target.build()).intValue()); assertEquals(6, staticSetting.get(target.build()).intValue()); assertEquals(9, target.build().getAsInt("archived.foo.bar", null).intValue()); target = Settings.builder().put(currentSettings); update = Settings.builder(); assertTrue(service.updateDynamicSettings(Settings.builder().putNull("*").build(), target, update, "node")); assertEquals(1, dynamicSetting.get(target.build()).intValue()); assertEquals(6, staticSetting.get(target.build()).intValue()); assertNull(target.build().getAsInt("archived.foo.bar", null)); } public void testAddConsumer() { Setting<Integer> testSetting = Setting.intSetting("foo.bar", 1, Property.Dynamic, Property.NodeScope); Setting<Integer> testSetting2 = Setting.intSetting("foo.bar.baz", 1, Property.Dynamic, Property.NodeScope); AbstractScopedSettings service = new ClusterSettings(Settings.EMPTY, Collections.singleton(testSetting)); AtomicInteger consumer = new AtomicInteger(); service.addSettingsUpdateConsumer(testSetting, consumer::set); AtomicInteger consumer2 = new AtomicInteger(); try { service.addSettingsUpdateConsumer(testSetting2, consumer2::set); fail("setting not registered"); } catch (IllegalArgumentException ex) { assertEquals("Setting is not registered for key [foo.bar.baz]", ex.getMessage()); } try { service.addSettingsUpdateConsumer(testSetting, testSetting2, (a, b) -> {consumer.set(a); consumer2.set(b);}); fail("setting not registered"); } catch (IllegalArgumentException ex) { assertEquals("Setting is not registered for key [foo.bar.baz]", ex.getMessage()); } assertEquals(0, consumer.get()); assertEquals(0, consumer2.get()); service.applySettings(Settings.builder().put("foo.bar", 2).put("foo.bar.baz", 15).build()); assertEquals(2, consumer.get()); assertEquals(0, consumer2.get()); } public void testAddConsumerAffix() { Setting.AffixSetting<Integer> intSetting = Setting.affixKeySetting("foo.", "bar", (k) -> Setting.intSetting(k, 1, Property.Dynamic, Property.NodeScope)); Setting.AffixSetting<List<Integer>> listSetting = Setting.affixKeySetting("foo.", "list", (k) -> Setting.listSetting(k, Arrays.asList("1"), Integer::parseInt, Property.Dynamic, Property.NodeScope)); AbstractScopedSettings service = new ClusterSettings(Settings.EMPTY,new HashSet<>(Arrays.asList(intSetting, listSetting))); Map<String, List<Integer>> listResults = new HashMap<>(); Map<String, Integer> intResults = new HashMap<>(); BiConsumer<String, Integer> intConsumer = intResults::put; BiConsumer<String, List<Integer>> listConsumer = listResults::put; service.addAffixUpdateConsumer(listSetting, listConsumer, (s, k) -> {}); service.addAffixUpdateConsumer(intSetting, intConsumer, (s, k) -> {}); assertEquals(0, listResults.size()); assertEquals(0, intResults.size()); service.applySettings(Settings.builder() .put("foo.test.bar", 2) .put("foo.test_1.bar", 7) .putArray("foo.test_list.list", "16", "17") .putArray("foo.test_list_1.list", "18", "19", "20") .build()); assertEquals(2, intResults.get("test").intValue()); assertEquals(7, intResults.get("test_1").intValue()); assertEquals(Arrays.asList(16, 17), listResults.get("test_list")); assertEquals(Arrays.asList(18, 19, 20), listResults.get("test_list_1")); assertEquals(2, listResults.size()); assertEquals(2, intResults.size()); listResults.clear(); intResults.clear(); service.applySettings(Settings.builder() .put("foo.test.bar", 2) .put("foo.test_1.bar", 8) .putArray("foo.test_list.list", "16", "17") .putNull("foo.test_list_1.list") .build()); assertNull("test wasn't changed", intResults.get("test")); assertEquals(8, intResults.get("test_1").intValue()); assertNull("test_list wasn't changed", listResults.get("test_list")); assertEquals(Arrays.asList(1), listResults.get("test_list_1")); // reset to default assertEquals(1, listResults.size()); assertEquals(1, intResults.size()); } public void testApply() { Setting<Integer> testSetting = Setting.intSetting("foo.bar", 1, Property.Dynamic, Property.NodeScope); Setting<Integer> testSetting2 = Setting.intSetting("foo.bar.baz", 1, Property.Dynamic, Property.NodeScope); AbstractScopedSettings service = new ClusterSettings(Settings.EMPTY, new HashSet<>(Arrays.asList(testSetting, testSetting2))); AtomicInteger consumer = new AtomicInteger(); service.addSettingsUpdateConsumer(testSetting, consumer::set); AtomicInteger consumer2 = new AtomicInteger(); service.addSettingsUpdateConsumer(testSetting2, consumer2::set, (s) -> assertTrue(s > 0)); AtomicInteger aC = new AtomicInteger(); AtomicInteger bC = new AtomicInteger(); service.addSettingsUpdateConsumer(testSetting, testSetting2, (a, b) -> {aC.set(a); bC.set(b);}); assertEquals(0, consumer.get()); assertEquals(0, consumer2.get()); assertEquals(0, aC.get()); assertEquals(0, bC.get()); try { service.applySettings(Settings.builder().put("foo.bar", 2).put("foo.bar.baz", -15).build()); fail("invalid value"); } catch (IllegalArgumentException ex) { assertEquals("illegal value can't update [foo.bar.baz] from [1] to [-15]", ex.getMessage()); } assertEquals(0, consumer.get()); assertEquals(0, consumer2.get()); assertEquals(0, aC.get()); assertEquals(0, bC.get()); try { service.validateUpdate(Settings.builder().put("foo.bar", 2).put("foo.bar.baz", -15).build()); fail("invalid value"); } catch (IllegalArgumentException ex) { assertEquals("illegal value can't update [foo.bar.baz] from [1] to [-15]", ex.getMessage()); } assertEquals(0, consumer.get()); assertEquals(0, consumer2.get()); assertEquals(0, aC.get()); assertEquals(0, bC.get()); service.validateUpdate(Settings.builder().put("foo.bar", 2).put("foo.bar.baz", 15).build()); assertEquals(0, consumer.get()); assertEquals(0, consumer2.get()); assertEquals(0, aC.get()); assertEquals(0, bC.get()); service.applySettings(Settings.builder().put("foo.bar", 2).put("foo.bar.baz", 15).build()); assertEquals(2, consumer.get()); assertEquals(15, consumer2.get()); assertEquals(2, aC.get()); assertEquals(15, bC.get()); } public void testGet() { ClusterSettings settings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); // group setting - complex matcher Setting setting = settings.get("cluster.routing.allocation.require.value"); assertEquals(setting, FilterAllocationDecider.CLUSTER_ROUTING_REQUIRE_GROUP_SETTING); setting = settings.get("cluster.routing.allocation.total_shards_per_node"); assertEquals(setting, ShardsLimitAllocationDecider.CLUSTER_TOTAL_SHARDS_PER_NODE_SETTING); // array settings - complex matcher assertNotNull(settings.get("transport.tracer.include." + randomIntBetween(1, 100))); assertSame(TransportService.TRACE_LOG_INCLUDE_SETTING, settings.get("transport.tracer.include." + randomIntBetween(1, 100))); // array settings - complex matcher - only accepts numbers assertNull(settings.get("transport.tracer.include.FOO")); } public void testIsDynamic(){ ClusterSettings settings = new ClusterSettings(Settings.EMPTY, new HashSet<>(Arrays.asList(Setting.intSetting("foo.bar", 1, Property.Dynamic, Property.NodeScope), Setting.intSetting("foo.bar.baz", 1, Property.NodeScope)))); assertFalse(settings.isDynamicSetting("foo.bar.baz")); assertTrue(settings.isDynamicSetting("foo.bar")); assertNotNull(settings.get("foo.bar.baz")); settings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); assertTrue(settings.isDynamicSetting("transport.tracer.include." + randomIntBetween(1, 100))); assertFalse(settings.isDynamicSetting("transport.tracer.include.BOOM")); assertTrue(settings.isDynamicSetting("cluster.routing.allocation.require.value")); } public void testIsFinal() { ClusterSettings settings = new ClusterSettings(Settings.EMPTY, new HashSet<>(Arrays.asList(Setting.intSetting("foo.int", 1, Property.Final, Property.NodeScope), Setting.groupSetting("foo.group.", Property.Final, Property.NodeScope), Setting.groupSetting("foo.list.", Property.Final, Property.NodeScope), Setting.intSetting("foo.int.baz", 1, Property.NodeScope)))); assertFalse(settings.isFinalSetting("foo.int.baz")); assertTrue(settings.isFinalSetting("foo.int")); assertFalse(settings.isFinalSetting("foo.list")); assertTrue(settings.isFinalSetting("foo.list.0.key")); assertTrue(settings.isFinalSetting("foo.list.key")); assertFalse(settings.isFinalSetting("foo.group")); assertTrue(settings.isFinalSetting("foo.group.key")); } public void testDiff() throws IOException { Setting<Integer> fooBarBaz = Setting.intSetting("foo.bar.baz", 1, Property.NodeScope); Setting<Integer> fooBar = Setting.intSetting("foo.bar", 1, Property.Dynamic, Property.NodeScope); Setting<Settings> someGroup = Setting.groupSetting("some.group.", Property.Dynamic, Property.NodeScope); Setting<Boolean> someAffix = Setting.affixKeySetting("some.prefix.", "somekey", (key) -> Setting.boolSetting(key, true, Property.NodeScope)); Setting<List<String>> foorBarQuux = Setting.listSetting("foo.bar.quux", Arrays.asList("a", "b", "c"), Function.identity(), Property.NodeScope); ClusterSettings settings = new ClusterSettings(Settings.EMPTY, new HashSet<>(Arrays.asList(fooBar, fooBarBaz, foorBarQuux, someGroup, someAffix))); Settings diff = settings.diff(Settings.builder().put("foo.bar", 5).build(), Settings.EMPTY); assertEquals(4, diff.size()); // 4 since foo.bar.quux has 3 values essentially assertThat(diff.getAsInt("foo.bar.baz", null), equalTo(1)); assertArrayEquals(diff.getAsArray("foo.bar.quux", null), new String[] {"a", "b", "c"}); diff = settings.diff( Settings.builder().put("foo.bar", 5).build(), Settings.builder().put("foo.bar.baz", 17).putArray("foo.bar.quux", "d", "e", "f").build()); assertEquals(4, diff.size()); // 4 since foo.bar.quux has 3 values essentially assertThat(diff.getAsInt("foo.bar.baz", null), equalTo(17)); assertArrayEquals(diff.getAsArray("foo.bar.quux", null), new String[] {"d", "e", "f"}); diff = settings.diff( Settings.builder().put("some.group.foo", 5).build(), Settings.builder().put("some.group.foobar", 17, "some.group.foo", 25).build()); assertEquals(6, diff.size()); // 6 since foo.bar.quux has 3 values essentially assertThat(diff.getAsInt("some.group.foobar", null), equalTo(17)); assertNull(diff.get("some.group.foo")); assertArrayEquals(diff.getAsArray("foo.bar.quux", null), new String[] {"a", "b", "c"}); assertThat(diff.getAsInt("foo.bar.baz", null), equalTo(1)); assertThat(diff.getAsInt("foo.bar", null), equalTo(1)); diff = settings.diff( Settings.builder().put("some.prefix.foo.somekey", 5).build(), Settings.builder().put("some.prefix.foobar.somekey", 17, "some.prefix.foo.somekey", 18).build()); assertEquals(6, diff.size()); // 6 since foo.bar.quux has 3 values essentially assertThat(diff.getAsInt("some.prefix.foobar.somekey", null), equalTo(17)); assertNull(diff.get("some.prefix.foo.somekey")); assertArrayEquals(diff.getAsArray("foo.bar.quux", null), new String[] {"a", "b", "c"}); assertThat(diff.getAsInt("foo.bar.baz", null), equalTo(1)); assertThat(diff.getAsInt("foo.bar", null), equalTo(1)); } public void testDiffWithAffixAndComplexMatcher() { Setting<Integer> fooBarBaz = Setting.intSetting("foo.bar.baz", 1, Property.NodeScope); Setting<Integer> fooBar = Setting.intSetting("foo.bar", 1, Property.Dynamic, Property.NodeScope); Setting<Settings> someGroup = Setting.groupSetting("some.group.", Property.Dynamic, Property.NodeScope); Setting<Boolean> someAffix = Setting.affixKeySetting("some.prefix.", "somekey", (key) -> Setting.boolSetting(key, true, Property.NodeScope)); Setting<List<String>> foorBarQuux = Setting.affixKeySetting("foo.", "quux", (key) -> Setting.listSetting(key, Arrays.asList("a", "b", "c"), Function.identity(), Property.NodeScope)); ClusterSettings settings = new ClusterSettings(Settings.EMPTY, new HashSet<>(Arrays.asList(fooBar, fooBarBaz, foorBarQuux, someGroup, someAffix))); Settings diff = settings.diff(Settings.builder().put("foo.bar", 5).build(), Settings.EMPTY); assertEquals(1, diff.size()); assertThat(diff.getAsInt("foo.bar.baz", null), equalTo(1)); assertNull(diff.getAsArray("foo.bar.quux", null)); // affix settings don't know their concrete keys diff = settings.diff( Settings.builder().put("foo.bar", 5).build(), Settings.builder().put("foo.bar.baz", 17).putArray("foo.bar.quux", "d", "e", "f").build()); assertEquals(4, diff.size()); assertThat(diff.getAsInt("foo.bar.baz", null), equalTo(17)); assertArrayEquals(diff.getAsArray("foo.bar.quux", null), new String[] {"d", "e", "f"}); diff = settings.diff( Settings.builder().put("some.group.foo", 5).build(), Settings.builder().put("some.group.foobar", 17, "some.group.foo", 25).build()); assertEquals(3, diff.size()); assertThat(diff.getAsInt("some.group.foobar", null), equalTo(17)); assertNull(diff.get("some.group.foo")); assertNull(diff.getAsArray("foo.bar.quux", null)); // affix settings don't know their concrete keys assertThat(diff.getAsInt("foo.bar.baz", null), equalTo(1)); assertThat(diff.getAsInt("foo.bar", null), equalTo(1)); diff = settings.diff( Settings.builder().put("some.prefix.foo.somekey", 5).build(), Settings.builder().put("some.prefix.foobar.somekey", 17, "some.prefix.foo.somekey", 18).build()); assertEquals(3, diff.size()); assertThat(diff.getAsInt("some.prefix.foobar.somekey", null), equalTo(17)); assertNull(diff.get("some.prefix.foo.somekey")); assertNull(diff.getAsArray("foo.bar.quux", null)); // affix settings don't know their concrete keys assertThat(diff.getAsInt("foo.bar.baz", null), equalTo(1)); assertThat(diff.getAsInt("foo.bar", null), equalTo(1)); diff = settings.diff( Settings.builder().put("some.prefix.foo.somekey", 5).build(), Settings.builder().put("some.prefix.foobar.somekey", 17, "some.prefix.foo.somekey", 18) .putArray("foo.bar.quux", "x", "y", "z") .putArray("foo.baz.quux", "d", "e", "f") .build()); assertEquals(9, diff.size()); assertThat(diff.getAsInt("some.prefix.foobar.somekey", null), equalTo(17)); assertNull(diff.get("some.prefix.foo.somekey")); assertArrayEquals(diff.getAsArray("foo.bar.quux", null), new String[] {"x", "y", "z"}); assertArrayEquals(diff.getAsArray("foo.baz.quux", null), new String[] {"d", "e", "f"}); assertThat(diff.getAsInt("foo.bar.baz", null), equalTo(1)); assertThat(diff.getAsInt("foo.bar", null), equalTo(1)); } public void testUpdateTracer() { ClusterSettings settings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); AtomicReference<List<String>> ref = new AtomicReference<>(); settings.addSettingsUpdateConsumer(TransportService.TRACE_LOG_INCLUDE_SETTING, ref::set); settings.applySettings(Settings.builder() .putArray("transport.tracer.include", "internal:index/shard/recovery/*", "internal:gateway/local*").build()); assertNotNull(ref.get().size()); assertEquals(ref.get().size(), 2); assertTrue(ref.get().contains("internal:index/shard/recovery/*")); assertTrue(ref.get().contains("internal:gateway/local*")); } public void testGetSetting() { IndexScopedSettings settings = new IndexScopedSettings( Settings.EMPTY, IndexScopedSettings.BUILT_IN_INDEX_SETTINGS); IndexScopedSettings copy = settings.copy(Settings.builder().put("index.store.type", "boom").build(), newIndexMeta("foo", Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 3).build())); assertEquals(3, copy.get(IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING).intValue()); assertEquals(1, copy.get(IndexMetaData.INDEX_NUMBER_OF_SHARDS_SETTING).intValue()); assertEquals("boom", copy.get(IndexModule.INDEX_STORE_TYPE_SETTING)); // test fallback to node settings } public void testValidateWithSuggestion() { IndexScopedSettings settings = new IndexScopedSettings( Settings.EMPTY, IndexScopedSettings.BUILT_IN_INDEX_SETTINGS); IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> settings.validate(Settings.builder().put("index.numbe_of_replica", "1").build())); assertEquals(iae.getMessage(), "unknown setting [index.numbe_of_replica] did you mean [index.number_of_replicas]?"); } public void testValidate() { IndexScopedSettings settings = new IndexScopedSettings( Settings.EMPTY, IndexScopedSettings.BUILT_IN_INDEX_SETTINGS); String unknownMsgSuffix = " please check that any required plugins are installed, or check the breaking changes documentation for" + " removed settings"; settings.validate(Settings.builder().put("index.store.type", "boom")); settings.validate(Settings.builder().put("index.store.type", "boom").build()); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> settings.validate(Settings.builder().put("index.store.type", "boom", "i.am.not.a.setting", true))); assertEquals("unknown setting [i.am.not.a.setting]" + unknownMsgSuffix, e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> settings.validate(Settings.builder().put("index.store.type", "boom", "i.am.not.a.setting", true).build())); assertEquals("unknown setting [i.am.not.a.setting]" + unknownMsgSuffix, e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> settings.validate(Settings.builder().put("index.store.type", "boom", "index.number_of_replicas", true).build())); assertEquals("Failed to parse value [true] for setting [index.number_of_replicas]", e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> settings.validate("index.number_of_replicas", Settings.builder().put("index.number_of_replicas", "true").build())); assertEquals("Failed to parse value [true] for setting [index.number_of_replicas]", e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> settings.validate("index.similarity.classic.type", Settings.builder().put("index.similarity.classic.type", "mine").build())); assertEquals("illegal value for [index.similarity.classic] cannot redefine built-in similarity", e.getMessage()); } public void testValidateSecureSettings() { MockSecureSettings secureSettings = new MockSecureSettings(); secureSettings.setString("some.secure.setting", "secret"); Settings settings = Settings.builder().setSecureSettings(secureSettings).build(); final ClusterSettings clusterSettings = new ClusterSettings(settings, Collections.emptySet()); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> clusterSettings.validate(settings)); assertThat(e.getMessage(), startsWith("unknown secure setting [some.secure.setting]")); ClusterSettings clusterSettings2 = new ClusterSettings(settings, Collections.singleton(SecureSetting.secureString("some.secure.setting", null))); clusterSettings2.validate(settings); } public void testDiffSecureSettings() { MockSecureSettings secureSettings = new MockSecureSettings(); secureSettings.setString("some.secure.setting", "secret"); Settings settings = Settings.builder().setSecureSettings(secureSettings).build(); ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, Collections.singleton(SecureSetting.secureString("some.secure.setting", null))); Settings diffed = clusterSettings.diff(Settings.EMPTY, settings); assertTrue(diffed.isEmpty()); } public static IndexMetaData newIndexMeta(String name, Settings indexSettings) { Settings build = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 1) .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) .put(indexSettings) .build(); IndexMetaData metaData = IndexMetaData.builder(name).settings(build).build(); return metaData; } public void testKeyPattern() { assertTrue(AbstractScopedSettings.isValidKey("a.b.c-b.d")); assertTrue(AbstractScopedSettings.isValidKey("a.b.c.d")); assertTrue(AbstractScopedSettings.isValidKey("a.b_012.c_b.d")); assertTrue(AbstractScopedSettings.isValidKey("a")); assertFalse(AbstractScopedSettings.isValidKey("a b")); assertFalse(AbstractScopedSettings.isValidKey("")); assertFalse(AbstractScopedSettings.isValidKey("\"")); try { new IndexScopedSettings( Settings.EMPTY, Collections.singleton(Setting.groupSetting("foo.bar.", Property.IndexScope))); fail(); } catch (IllegalArgumentException e) { assertEquals("illegal settings key: [foo.bar.] must start with [index.]", e.getMessage()); } try { new IndexScopedSettings( Settings.EMPTY, Collections.singleton(Setting.simpleString("foo.bar", Property.IndexScope))); fail(); } catch (IllegalArgumentException e) { assertEquals("illegal settings key: [foo.bar] must start with [index.]", e.getMessage()); } try { new IndexScopedSettings( Settings.EMPTY, Collections.singleton(Setting.groupSetting("index. foo.", Property.IndexScope))); fail(); } catch (IllegalArgumentException e) { assertEquals("illegal settings key: [index. foo.]", e.getMessage()); } new IndexScopedSettings( Settings.EMPTY, Collections.singleton(Setting.groupSetting("index.", Property.IndexScope))); try { new IndexScopedSettings( Settings.EMPTY, Collections.singleton(Setting.boolSetting("index.", true, Property.IndexScope))); fail(); } catch (IllegalArgumentException e) { assertEquals("illegal settings key: [index.]", e.getMessage()); } new IndexScopedSettings( Settings.EMPTY, Collections.singleton(Setting.boolSetting("index.boo", true, Property.IndexScope))); new ClusterSettings( Settings.EMPTY, Collections.singleton(Setting.boolSetting("index.boo", true, Property.NodeScope))); } public void testAffixKeyPattern() { assertTrue(AbstractScopedSettings.isValidAffixKey("prefix.*.suffix")); assertTrue(AbstractScopedSettings.isValidAffixKey("prefix.*.split.suffix")); assertTrue(AbstractScopedSettings.isValidAffixKey("split.prefix.*.split.suffix")); assertFalse(AbstractScopedSettings.isValidAffixKey("prefix.*.suffix.")); assertFalse(AbstractScopedSettings.isValidAffixKey("prefix.*")); assertFalse(AbstractScopedSettings.isValidAffixKey("*.suffix")); assertFalse(AbstractScopedSettings.isValidAffixKey("*")); assertFalse(AbstractScopedSettings.isValidAffixKey("")); } public void testLoggingUpdates() { final Level level = ESLoggerFactory.getRootLogger().getLevel(); final Level testLevel = ESLoggerFactory.getLogger("test").getLevel(); Level property = randomFrom(Level.values()); Settings.Builder builder = Settings.builder().put("logger.level", property); try { ClusterSettings settings = new ClusterSettings(builder.build(), ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); IllegalArgumentException ex = expectThrows( IllegalArgumentException.class, () -> settings.validate(Settings.builder().put("logger._root", "boom").build())); assertEquals("Unknown level constant [BOOM].", ex.getMessage()); assertEquals(level, ESLoggerFactory.getRootLogger().getLevel()); settings.applySettings(Settings.builder().put("logger._root", "TRACE").build()); assertEquals(Level.TRACE, ESLoggerFactory.getRootLogger().getLevel()); settings.applySettings(Settings.builder().build()); assertEquals(property, ESLoggerFactory.getRootLogger().getLevel()); settings.applySettings(Settings.builder().put("logger.test", "TRACE").build()); assertEquals(Level.TRACE, ESLoggerFactory.getLogger("test").getLevel()); settings.applySettings(Settings.builder().build()); assertEquals(property, ESLoggerFactory.getLogger("test").getLevel()); } finally { Loggers.setLevel(ESLoggerFactory.getRootLogger(), level); Loggers.setLevel(ESLoggerFactory.getLogger("test"), testLevel); } } public void testFallbackToLoggerLevel() { final Level level = ESLoggerFactory.getRootLogger().getLevel(); try { ClusterSettings settings = new ClusterSettings(Settings.builder().put("logger.level", "ERROR").build(), ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); assertEquals(level, ESLoggerFactory.getRootLogger().getLevel()); settings.applySettings(Settings.builder().put("logger._root", "TRACE").build()); assertEquals(Level.TRACE, ESLoggerFactory.getRootLogger().getLevel()); settings.applySettings(Settings.builder().build()); // here we fall back to 'logger.level' which is our default. assertEquals(Level.ERROR, ESLoggerFactory.getRootLogger().getLevel()); } finally { Loggers.setLevel(ESLoggerFactory.getRootLogger(), level); } } public void testOverlappingComplexMatchSettings() { Set<Setting<?>> settings = new LinkedHashSet<>(2); final boolean groupFirst = randomBoolean(); final Setting<?> groupSetting = Setting.groupSetting("foo.", Property.NodeScope); final Setting<?> listSetting = Setting.listSetting("foo.bar", Collections.emptyList(), Function.identity(), Property.NodeScope); settings.add(groupFirst ? groupSetting : listSetting); settings.add(groupFirst ? listSetting : groupSetting); try { new ClusterSettings(Settings.EMPTY, settings); fail("an exception should have been thrown because settings overlap"); } catch (IllegalArgumentException e) { if (groupFirst) { assertEquals("complex setting key: [foo.bar] overlaps existing setting key: [foo.]", e.getMessage()); } else { assertEquals("complex setting key: [foo.] overlaps existing setting key: [foo.bar]", e.getMessage()); } } } public void testUpdateNumberOfShardsFail() { IndexScopedSettings settings = new IndexScopedSettings(Settings.EMPTY, IndexScopedSettings.BUILT_IN_INDEX_SETTINGS); IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> settings.updateSettings(Settings.builder().put("index.number_of_shards", 8).build(), Settings.builder(), Settings.builder(), "index")); assertThat(ex.getMessage(), containsString("final index setting [index.number_of_shards], not updateable")); } public void testFinalSettingUpdateFail() { Setting<Integer> finalSetting = Setting.intSetting("some.final.setting", 1, Property.Final, Property.NodeScope); Setting<Settings> finalGroupSetting = Setting.groupSetting("some.final.group.", Property.Final, Property.NodeScope); Settings currentSettings = Settings.builder() .put("some.final.setting", 9) .put("some.final.group.foo", 7) .build(); ClusterSettings service = new ClusterSettings(currentSettings , new HashSet<>(Arrays.asList(finalSetting, finalGroupSetting))); IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, () -> service.updateDynamicSettings(Settings.builder().put("some.final.setting", 8).build(), Settings.builder().put(currentSettings), Settings.builder(), "node")); assertThat(exc.getMessage(), containsString("final node setting [some.final.setting]")); exc = expectThrows(IllegalArgumentException.class, () -> service.updateDynamicSettings(Settings.builder().putNull("some.final.setting").build(), Settings.builder().put(currentSettings), Settings.builder(), "node")); assertThat(exc.getMessage(), containsString("final node setting [some.final.setting]")); exc = expectThrows(IllegalArgumentException.class, () -> service.updateSettings(Settings.builder().put("some.final.group.new", 8).build(), Settings.builder().put(currentSettings), Settings.builder(), "node")); assertThat(exc.getMessage(), containsString("final node setting [some.final.group.new]")); exc = expectThrows(IllegalArgumentException.class, () -> service.updateSettings(Settings.builder().put("some.final.group.foo", 5).build(), Settings.builder().put(currentSettings), Settings.builder(), "node")); assertThat(exc.getMessage(), containsString("final node setting [some.final.group.foo]")); } }