simplify dynamic key setting and make it generally useful

This commit is contained in:
Simon Willnauer 2016-01-28 16:16:24 +01:00
parent 23d41ce42f
commit 3509ceaa80
3 changed files with 53 additions and 25 deletions

View File

@ -37,28 +37,7 @@ import java.util.regex.Pattern;
public abstract class ESLoggerFactory {
public static final Setting<LogLevel> LOG_DEFAULT_LEVEL_SETTING = new Setting<>("logger.level", LogLevel.INFO.name(), LogLevel::parse, false, Setting.Scope.CLUSTER);
public static final Setting<LogLevel> LOG_LEVEL_SETTING = new Setting<LogLevel>("logger.", LogLevel.INFO.name(), LogLevel::parse, true, Setting.Scope.CLUSTER) {
private final Pattern KEY_PATTERN = Pattern.compile("^logger[.](?:[-\\w]+[.])*[-\\w]+$$");
@Override
protected boolean isGroupSetting() {
return true;
}
@Override
public boolean match(String toTest) {
return KEY_PATTERN.matcher(toTest).matches();
}
@Override
public Setting<LogLevel> getConcreteSetting(String key) {
if (match(key)) {
return new Setting<>(key, LogLevel.WARN.name(), LogLevel::parse, true, Setting.Scope.CLUSTER);
} else {
throw new IllegalArgumentException("key must match setting but didn't ["+key +"]");
}
}
};
public static final Setting<LogLevel> LOG_LEVEL_SETTING = Setting.dynamicKeySetting("logger.", LogLevel.INFO.name(), LogLevel::parse, true, Setting.Scope.CLUSTER);
private static volatile ESLoggerFactory defaultFactory = new JdkESLoggerFactory();

View File

@ -111,7 +111,7 @@ public class Setting<T> extends ToXContentToBytes {
* rather than a single value. The key, see {@link #getKey()}, in contrast to non-group settings is a prefix like <tt>cluster.store.</tt>
* that matches all settings with this prefix.
*/
protected boolean isGroupSetting() {
boolean isGroupSetting() {
return false;
}
@ -201,6 +201,7 @@ public class Setting<T> extends ToXContentToBytes {
}
public Setting<T> getConcreteSetting(String key) {
assert key.startsWith(this.getKey()) : "was " + key + " expected: " + getKey(); // we use startsWith here since the key might be foo.bar.0 if it's an array
return this;
}
@ -453,8 +454,6 @@ public class Setting<T> extends ToXContentToBytes {
}
}
public static Setting<Settings> groupSetting(String key, boolean dynamic, Scope scope) {
if (key.endsWith(".") == false) {
throw new IllegalArgumentException("key must end with a '.'");
@ -562,4 +561,38 @@ public class Setting<T> extends ToXContentToBytes {
public int hashCode() {
return Objects.hash(key);
}
/**
* This setting type allows to validate settings that have the same type and a common prefix. For instance feature.${type}=[true|false]
* can easily be added with this setting. Yet, dynamic key settings don't support updaters our of the box unless {@link #getConcreteSetting(String)}
* is used to pull the updater.
*/
public static <T> Setting<T> dynamicKeySetting(String key, String defaultValue, Function<String, T> parser, boolean dynamic, Scope scope) {
return new Setting<T>(key, defaultValue, parser, dynamic, scope) {
@Override
boolean isGroupSetting() {
return true;
}
@Override
public boolean match(String toTest) {
return toTest.startsWith(getKey());
}
@Override
AbstractScopedSettings.SettingUpdater<T> newUpdater(Consumer<T> consumer, ESLogger logger, Consumer<T> validator) {
throw new UnsupportedOperationException("dynamic settings can't be updated use #getConcreteSetting for updating");
}
@Override
public Setting<T> getConcreteSetting(String key) {
if (match(key)) {
return new Setting<>(key, defaultValue, parser, dynamic, scope);
} else {
throw new IllegalArgumentException("key must match setting but didn't ["+key +"]");
}
}
};
}
}

View File

@ -346,6 +346,22 @@ public class SettingTests extends ESTestCase {
assertFalse(listSetting.match("foo_bar.1"));
assertTrue(listSetting.match("foo.bar"));
assertTrue(listSetting.match("foo.bar." + randomIntBetween(0,10000)));
}
public void testDynamicKeySetting() {
Setting<Boolean> setting = Setting.dynamicKeySetting("foo.", "false", Boolean::parseBoolean, false, Setting.Scope.CLUSTER);
assertTrue(setting.hasComplexMatcher());
assertTrue(setting.match("foo.bar"));
assertFalse(setting.match("foo"));
Setting<Boolean> concreteSetting = setting.getConcreteSetting("foo.bar");
assertTrue(concreteSetting.get(Settings.builder().put("foo.bar", "true").build()));
assertFalse(concreteSetting.get(Settings.builder().put("foo.baz", "true").build()));
try {
setting.getConcreteSetting("foo");
fail();
} catch (IllegalArgumentException ex) {
assertEquals("key must match setting but didn't [foo]", ex.getMessage());
}
}
}