diff --git a/server/src/main/java/org/elasticsearch/common/settings/Setting.java b/server/src/main/java/org/elasticsearch/common/settings/Setting.java index 0062bd24f56..51d9e570018 100644 --- a/server/src/main/java/org/elasticsearch/common/settings/Setting.java +++ b/server/src/main/java/org/elasticsearch/common/settings/Setting.java @@ -438,7 +438,16 @@ public class Setting implements ToXContentObject { map = new HashMap<>(); while (it.hasNext()) { final Setting setting = it.next(); - map.put(setting, setting.get(settings, false)); // we have to disable validation or we will stack overflow + if (setting instanceof AffixSetting) { + // Collect all possible concrete settings + AffixSetting as = ((AffixSetting)setting); + for (String ns : as.getNamespaces(settings)) { + Setting s = as.getConcreteSettingForNamespace(ns); + map.put(s, s.get(settings, false)); + } + } else { + map.put(setting, setting.get(settings, false)); // we have to disable validation or we will stack overflow + } } } else { map = Collections.emptyMap(); diff --git a/server/src/test/java/org/elasticsearch/common/settings/SettingTests.java b/server/src/test/java/org/elasticsearch/common/settings/SettingTests.java index a4b52f9d1d2..aac92f4ce5f 100644 --- a/server/src/test/java/org/elasticsearch/common/settings/SettingTests.java +++ b/server/src/test/java/org/elasticsearch/common/settings/SettingTests.java @@ -830,6 +830,59 @@ public class SettingTests extends ESTestCase { assertEquals("[\"testelement\"]", listAffixSetting.getDefaultRaw(Settings.EMPTY)); } + public void testAffixSettingsValidatorDependencies() { + Setting affix = Setting.affixKeySetting("abc.", "def", k -> Setting.intSetting(k, 10)); + Setting fix0 = Setting.intSetting("abc.tuv", 20, 0); + Setting fix1 = Setting.intSetting("abc.qrx", 20, 0, new Setting.Validator() { + @Override + public void validate(Integer value) {} + + String toString(Map, Object> s) { + return s.entrySet().stream().map(e -> e.getKey().getKey() + ":" + e.getValue().toString()).sorted() + .collect(Collectors.joining(",")); + } + + @Override + public void validate(Integer value, Map, Object> settings, boolean isPresent) { + if (settings.get(fix0).equals(fix0.getDefault(Settings.EMPTY))) { + settings.remove(fix0); + } + if (settings.size() == 1) { + throw new IllegalArgumentException(toString(settings)); + } else if (settings.size() == 2) { + throw new IllegalArgumentException(toString(settings)); + } + } + + @Override + public Iterator> settings() { + List> a = Arrays.asList(affix, fix0); + return a.iterator(); + } + }); + + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, + () -> fix1.get(Settings.builder().put("abc.1.def", 11).put("abc.2.def", 12).put("abc.qrx", 11).build())); + assertThat(e.getMessage(), is("abc.1.def:11,abc.2.def:12")); + + e = expectThrows(IllegalArgumentException.class, + () -> fix1.get(Settings.builder().put("abc.3.def", 13).put("abc.qrx", 20).build())); + assertThat(e.getMessage(), is("abc.3.def:13")); + + e = expectThrows(IllegalArgumentException.class, + () -> fix1.get(Settings.builder().put("abc.4.def", 14).put("abc.qrx", 20).put("abc.tuv", 50).build())); + assertThat(e.getMessage(), is("abc.4.def:14,abc.tuv:50")); + + assertEquals( + fix1.get(Settings.builder() + .put("abc.3.def", 13).put("abc.1.def", 11).put("abc.2.def", 12).put("abc.qrx", 20) + .build()), + Integer.valueOf(20) + ); + + assertEquals(fix1.get(Settings.builder().put("abc.qrx", 30).build()), Integer.valueOf(30)); + } + public void testMinMaxInt() { Setting integerSetting = Setting.intSetting("foo.bar", 1, 0, 10, Property.NodeScope); try {