From 429b372edbd3b346e226ae642938b9bb1b1d971f Mon Sep 17 00:00:00 2001 From: Simon Willnauer Date: Tue, 26 Jan 2016 16:19:13 +0100 Subject: [PATCH] Validate tribe node settings on startup --- .../common/settings/SettingsModule.java | 37 ++++++--- .../common/settings/SettingsModuleTests.java | 81 +++++++++++++++++++ 2 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 core/src/test/java/org/elasticsearch/common/settings/SettingsModuleTests.java diff --git a/core/src/main/java/org/elasticsearch/common/settings/SettingsModule.java b/core/src/main/java/org/elasticsearch/common/settings/SettingsModule.java index eec6e734229..24fe7be56c6 100644 --- a/core/src/main/java/org/elasticsearch/common/settings/SettingsModule.java +++ b/core/src/main/java/org/elasticsearch/common/settings/SettingsModule.java @@ -24,6 +24,7 @@ import org.elasticsearch.common.inject.AbstractModule; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.function.Predicate; /** * A module that binds the provided settings to the {@link Settings} interface. @@ -54,18 +55,13 @@ public class SettingsModule extends AbstractModule { final ClusterSettings clusterSettings = new ClusterSettings(settings, new HashSet<>(this.clusterSettings.values())); // by now we are fully configured, lets check node level settings for unregistered index settings indexScopedSettings.validate(settings.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE)); - // we can't call this method yet since we have not all node level settings registered. - // yet we can validate the ones we have registered to not have invalid values. this is better than nothing - // and progress over perfection and we fail as soon as possible. - // clusterSettings.validate(settings.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE.negate())); - for (Map.Entry entry : settings.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE.negate()).getAsMap().entrySet()) { - if (clusterSettings.get(entry.getKey()) != null) { - clusterSettings.validate(entry.getKey(), settings); - } else if (AbstractScopedSettings.isValidKey(entry.getKey()) == false) { - throw new IllegalArgumentException("illegal settings key: [" + entry.getKey() + "]"); - } + Predicate noIndexSettingPredicate = IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE.negate(); + Predicate noTribePredicate = (s) -> s.startsWith("tribe.") == false; + for (Map.Entry entry : settings.filter(noTribePredicate.and(noIndexSettingPredicate)).getAsMap().entrySet()) { + validateClusterSetting(clusterSettings, entry.getKey(), settings); } + validateTribeSettings(settings, clusterSettings); bind(Settings.class).toInstance(settings); bind(SettingsFilter.class).toInstance(settingsFilter); @@ -90,4 +86,25 @@ public class SettingsModule extends AbstractModule { } } + public void validateTribeSettings(Settings settings, ClusterSettings clusterSettings) { + Map groups = settings.getGroups("tribe."); + for (Map.Entry tribeSettings : groups.entrySet()) { + for (Map.Entry entry : tribeSettings.getValue().getAsMap().entrySet()) { + validateClusterSetting(clusterSettings, entry.getKey(), tribeSettings.getValue()); + } + } + } + + private final void validateClusterSetting(ClusterSettings clusterSettings, String key, Settings settings) { + // we can't call this method yet since we have not all node level settings registered. + // yet we can validate the ones we have registered to not have invalid values. this is better than nothing + // and progress over perfection and we fail as soon as possible. + // clusterSettings.validate(settings.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE.negate())); + if (clusterSettings.get(key) != null) { + clusterSettings.validate(key, settings); + } else if (AbstractScopedSettings.isValidKey(key) == false) { + throw new IllegalArgumentException("illegal settings key: [" + key + "]"); + } + } + } diff --git a/core/src/test/java/org/elasticsearch/common/settings/SettingsModuleTests.java b/core/src/test/java/org/elasticsearch/common/settings/SettingsModuleTests.java new file mode 100644 index 00000000000..731957cba06 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/common/settings/SettingsModuleTests.java @@ -0,0 +1,81 @@ +/* + * 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.elasticsearch.common.inject.ModuleTestCase; + +public class SettingsModuleTests extends ModuleTestCase { + + public void testValidate() { + { + Settings settings = Settings.builder().put("cluster.routing.allocation.balance.shard", "2.0").build(); + SettingsModule module = new SettingsModule(settings, new SettingsFilter(Settings.EMPTY)); + assertInstanceBinding(module, Settings.class, (s) -> s == settings); + } + { + Settings settings = Settings.builder().put("cluster.routing.allocation.balance.shard", "[2.0]").build(); + SettingsModule module = new SettingsModule(settings, new SettingsFilter(Settings.EMPTY)); + try { + assertInstanceBinding(module, Settings.class, (s) -> s == settings); + fail(); + } catch (IllegalArgumentException ex) { + assertEquals("Failed to parse value [[2.0]] for setting [cluster.routing.allocation.balance.shard]", ex.getMessage()); + } + } + } + + public void testRegisterSettings() { + { + Settings settings = Settings.builder().put("some.custom.setting", "2.0").build(); + SettingsModule module = new SettingsModule(settings, new SettingsFilter(Settings.EMPTY)); + module.registerSetting(Setting.floatSetting("some.custom.setting", 1.0f, false, Setting.Scope.CLUSTER)); + assertInstanceBinding(module, Settings.class, (s) -> s == settings); + } + { + Settings settings = Settings.builder().put("some.custom.setting", "false").build(); + SettingsModule module = new SettingsModule(settings, new SettingsFilter(Settings.EMPTY)); + module.registerSetting(Setting.floatSetting("some.custom.setting", 1.0f, false, Setting.Scope.CLUSTER)); + try { + assertInstanceBinding(module, Settings.class, (s) -> s == settings); + fail(); + } catch (IllegalArgumentException ex) { + assertEquals("Failed to parse value [false] for setting [some.custom.setting]", ex.getMessage()); + } + } + } + + public void testTribeSetting() { + { + Settings settings = Settings.builder().put("tribe.t1.cluster.routing.allocation.balance.shard", "2.0").build(); + SettingsModule module = new SettingsModule(settings, new SettingsFilter(Settings.EMPTY)); + assertInstanceBinding(module, Settings.class, (s) -> s == settings); + } + { + Settings settings = Settings.builder().put("tribe.t1.cluster.routing.allocation.balance.shard", "[2.0]").build(); + SettingsModule module = new SettingsModule(settings, new SettingsFilter(Settings.EMPTY)); + try { + assertInstanceBinding(module, Settings.class, (s) -> s == settings); + fail(); + } catch (IllegalArgumentException ex) { + assertEquals("Failed to parse value [[2.0]] for setting [cluster.routing.allocation.balance.shard]", ex.getMessage()); + } + } + } +}