Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add infrastructure to upgrade settings #33536

Merged
merged 18 commits into from
Sep 10, 2018
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,12 @@ public void onFailure(String source, Exception e) {

@Override
public ClusterState execute(final ClusterState currentState) {
ClusterState clusterState =
updater.updateSettings(currentState, request.transientSettings(), request.persistentSettings(), logger);
final ClusterState clusterState =
updater.updateSettings(
currentState,
clusterSettings.upgradeSettings(request.transientSettings()),
clusterSettings.upgradeSettings(request.persistentSettings()),
logger);
changed = clusterState != currentState;
return clusterState;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

package org.elasticsearch.client.transport;

import org.elasticsearch.core.internal.io.IOUtils;
import org.elasticsearch.action.Action;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionModule;
Expand All @@ -44,6 +43,7 @@
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.util.PageCacheRecycler;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.core.internal.io.IOUtils;
import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.node.InternalSettingsPreparer;
Expand Down Expand Up @@ -146,7 +146,8 @@ private static ClientTemplate buildTemplate(Settings providedSettings, Settings
for (final ExecutorBuilder<?> builder : threadPool.builders()) {
additionalSettings.addAll(builder.getRegisteredSettings());
}
SettingsModule settingsModule = new SettingsModule(settings, additionalSettings, additionalSettingsFilter);
SettingsModule settingsModule =
new SettingsModule(settings, additionalSettings, additionalSettingsFilter, Collections.emptyList());

SearchModule searchModule = new SearchModule(settings, true, pluginsService.filterPlugins(SearchPlugin.class));
IndicesModule indicesModule = new IndicesModule(Collections.emptyList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.regex.Regex;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -38,6 +39,7 @@
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand All @@ -52,14 +54,29 @@ public abstract class AbstractScopedSettings extends AbstractComponent {
private final List<SettingUpdater<?>> settingUpdaters = new CopyOnWriteArrayList<>();
private final Map<String, Setting<?>> complexMatchers;
private final Map<String, Setting<?>> keySettings;
private final Map<Setting<?>, Function<Map.Entry<String, String>, Map.Entry<String, String>>> settingUpgraders;
private final Setting.Property scope;
private static final Pattern KEY_PATTERN = Pattern.compile("^(?:[-\\w]+[.])*[-\\w]+$");
private static final Pattern GROUP_KEY_PATTERN = Pattern.compile("^(?:[-\\w]+[.])+$");
private static final Pattern AFFIX_KEY_PATTERN = Pattern.compile("^(?:[-\\w]+[.])+[*](?:[.][-\\w]+)+$");

protected AbstractScopedSettings(Settings settings, Set<Setting<?>> settingsSet, Setting.Property scope) {
protected AbstractScopedSettings(
final Settings settings,
final Set<Setting<?>> settingsSet,
final List<SettingUpgrader<?>> settingUpgraders,
jasontedor marked this conversation as resolved.
Show resolved Hide resolved
final Setting.Property scope) {
super(settings);
this.lastSettingsApplied = Settings.EMPTY;

this.settingUpgraders =
Collections.unmodifiableMap(
settingUpgraders
.stream()
.collect(
Collectors.toMap(
SettingUpgrader::getSetting,
u -> e -> new AbstractMap.SimpleEntry<>(u.getKey(e.getKey()), u.getValue(e.getValue())))));

this.scope = scope;
Map<String, Setting<?>> complexMatchers = new HashMap<>();
Map<String, Setting<?>> keySettings = new HashMap<>();
Expand Down Expand Up @@ -97,6 +114,7 @@ protected AbstractScopedSettings(Settings nodeSettings, Settings scopeSettings,
this.scope = other.scope;
complexMatchers = other.complexMatchers;
keySettings = other.keySettings;
settingUpgraders = Collections.unmodifiableMap(new HashMap<>(other.settingUpgraders));
settingUpdaters.addAll(other.settingUpdaters);
}

Expand Down Expand Up @@ -757,6 +775,32 @@ private static Setting<?> findOverlappingSetting(Setting<?> newSetting, Map<Stri
return null;
}

/**
* Upgrade all settings eligible for upgrade in the specified settings instance.
*
* @param settings the settings instance that might contain settings to be upgraded
* @return a new settings instance if any settings required upgrade, otherwise the same settings instance as specified
*/
public Settings upgradeSettings(final Settings settings) {
final Settings.Builder builder = Settings.builder();
boolean changed = false; // track if any settings were upgraded
for (final String key : settings.keySet()) {
final Setting<?> setting = getRaw(key);
final Function<Map.Entry<String, String>, Map.Entry<String, String>> upgrader = settingUpgraders.get(setting);
if (upgrader == null) {
// the setting does not have an upgrader, copy the setting
builder.copy(key, settings);
} else {
// the setting has an upgrader, so mark that we have changed a setting and apply the upgrade logic
changed = true;
final Map.Entry<String, String> upgrade = upgrader.apply(new Entry(key, settings));
jasontedor marked this conversation as resolved.
Show resolved Hide resolved
builder.put(upgrade.getKey(), upgrade.getValue());
}
}
// we only return a new instance if there was an upgrade
return changed ? builder.build() : settings;
}

/**
* Archives invalid or unknown settings. Any setting that is not recognized or fails validation
* will be archived. This means the setting is prefixed with {@value ARCHIVED_SETTINGS_PREFIX}
Expand Down Expand Up @@ -847,4 +891,5 @@ public String setValue(String value) {
public boolean isPrivateSetting(String key) {
return false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,21 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;

/**
* Encapsulates all valid cluster level settings.
*/
public final class ClusterSettings extends AbstractScopedSettings {
public ClusterSettings(Settings nodeSettings, Set<Setting<?>> settingsSet) {
super(nodeSettings, settingsSet, Property.NodeScope);
public ClusterSettings(final Settings nodeSettings, final Set<Setting<?>> settingsSet) {
this(nodeSettings, settingsSet, Collections.emptyList());
}

public ClusterSettings(
final Settings nodeSettings, final Set<Setting<?>> settingsSet, final List<SettingUpgrader<?>> settingUpgraders) {
super(nodeSettings, settingsSet, settingUpgraders, Property.NodeScope);
addSettingsUpdater(new LoggingSettingUpdater(nodeSettings));
}

Expand Down Expand Up @@ -436,4 +442,7 @@ public void apply(Settings value, Settings current, Settings previous) {
IndexGraveyard.SETTING_MAX_TOMBSTONES,
EnableAssignmentDecider.CLUSTER_TASKS_ALLOCATION_ENABLE_SETTING
)));

public static List<SettingUpgrader<?>> BUILT_IN_SETTING_UPGRADERS = Collections.emptyList();

}
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings {
public static final IndexScopedSettings DEFAULT_SCOPED_SETTINGS = new IndexScopedSettings(Settings.EMPTY, BUILT_IN_INDEX_SETTINGS);

public IndexScopedSettings(Settings settings, Set<Setting<?>> settingsSet) {
super(settings, settingsSet, Property.IndexScope);
super(settings, settingsSet, Collections.emptyList(), Property.IndexScope);
}

private IndexScopedSettings(Settings settings, IndexScopedSettings other, IndexMetaData metaData) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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;

/**
* Represents the logic to upgrade a setting.
*
* @param <T> the type of the underlying setting
*/
public interface SettingUpgrader<T> {

/**
* The setting upgraded by this upgrader.
*
* @return the setting
*/
Setting<T> getSetting();

/**
* The logic to upgrade the setting key, for example by mapping the old setting key to the new setting key.
*
* @param key the setting key to upgrade
* @return the upgraded setting key
*/
String getKey(String key);

/**
* The logic to upgrade the setting value.
*
* @param value the setting value to upgrade
* @return the upgraded setting value
*/
default String getValue(final String value) {
return value;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.elasticsearch.common.xcontent.XContentType;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -54,10 +55,14 @@ public class SettingsModule implements Module {
private final SettingsFilter settingsFilter;

public SettingsModule(Settings settings, Setting<?>... additionalSettings) {
this(settings, Arrays.asList(additionalSettings), Collections.emptyList());
this(settings, Arrays.asList(additionalSettings), Collections.emptyList(), Collections.emptyList());
}

public SettingsModule(Settings settings, List<Setting<?>> additionalSettings, List<String> settingsFilter) {
public SettingsModule(
Settings settings,
List<Setting<?>> additionalSettings,
List<String> settingsFilter,
List<SettingUpgrader<?>> settingUpgraders) {
logger = Loggers.getLogger(getClass(), settings);
this.settings = settings;
for (Setting<?> setting : ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) {
Expand All @@ -70,12 +75,20 @@ public SettingsModule(Settings settings, List<Setting<?>> additionalSettings, Li
for (Setting<?> setting : additionalSettings) {
registerSetting(setting);
}

for (String filter : settingsFilter) {
registerSettingsFilter(filter);
}
final List<SettingUpgrader<?>> clusterSettingUpgraders = new ArrayList<>();
for (final SettingUpgrader<?> settingUpgrader : ClusterSettings.BUILT_IN_SETTING_UPGRADERS) {
assert settingUpgrader.getSetting().hasNodeScope() : settingUpgrader.getSetting().getKey();
clusterSettingUpgraders.add(settingUpgrader);
}
for (final SettingUpgrader<?> settingUpgrader : settingUpgraders) {
assert settingUpgrader.getSetting().hasNodeScope() : settingUpgrader.getSetting().getKey();
clusterSettingUpgraders.add(settingUpgrader);
}
this.indexScopedSettings = new IndexScopedSettings(settings, new HashSet<>(this.indexSettings.values()));
this.clusterSettings = new ClusterSettings(settings, new HashSet<>(this.nodeSettings.values()));
this.clusterSettings = new ClusterSettings(settings, new HashSet<>(this.nodeSettings.values()), clusterSettingUpgraders);
Settings indexSettings = settings.filter((s) -> (s.startsWith("index.") &&
// special case - we want to get Did you mean indices.query.bool.max_clause_count
// which means we need to by-pass this check for this setting
Expand Down Expand Up @@ -205,4 +218,5 @@ public ClusterSettings getClusterSettings() {
public SettingsFilter getSettingsFilter() {
return settingsFilter;
}

}
11 changes: 8 additions & 3 deletions server/src/main/java/org/elasticsearch/gateway/Gateway.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,20 +137,25 @@ public void performStateRecovery(final GatewayStateRecoveredListener listener) t
}
}
}
final ClusterState.Builder builder = upgradeAndArchiveUnknownOrInvalidSettings(metaDataBuilder);
listener.onSuccess(builder.build());
}

ClusterState.Builder upgradeAndArchiveUnknownOrInvalidSettings(MetaData.Builder metaDataBuilder) {
final ClusterSettings clusterSettings = clusterService.getClusterSettings();
metaDataBuilder.persistentSettings(
clusterSettings.archiveUnknownOrInvalidSettings(
metaDataBuilder.persistentSettings(),
clusterSettings.upgradeSettings(metaDataBuilder.persistentSettings()),
e -> logUnknownSetting("persistent", e),
(e, ex) -> logInvalidSetting("persistent", e, ex)));
metaDataBuilder.transientSettings(
clusterSettings.archiveUnknownOrInvalidSettings(
metaDataBuilder.transientSettings(),
clusterSettings.upgradeSettings(metaDataBuilder.transientSettings()),
e -> logUnknownSetting("transient", e),
(e, ex) -> logInvalidSetting("transient", e, ex)));
ClusterState.Builder builder = ClusterState.builder(ClusterName.CLUSTER_NAME_SETTING.get(settings));
builder.metaData(metaDataBuilder);
listener.onSuccess(builder.build());
return builder;
}

private void logUnknownSetting(String settingType, Map.Entry<String, String> e) {
Expand Down
12 changes: 11 additions & 1 deletion server/src/main/java/org/elasticsearch/node/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.SettingUpgrader;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsModule;
import org.elasticsearch.common.transport.BoundTransportAddress;
Expand Down Expand Up @@ -151,6 +152,7 @@
import org.elasticsearch.watcher.ResourceWatcherService;

import javax.net.ssl.SNIHostName;

import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.IOException;
Expand Down Expand Up @@ -360,7 +362,15 @@ protected Node(
AnalysisModule analysisModule = new AnalysisModule(this.environment, pluginsService.filterPlugins(AnalysisPlugin.class));
// this is as early as we can validate settings at this point. we already pass them to ScriptModule as well as ThreadPool
// so we might be late here already
final SettingsModule settingsModule = new SettingsModule(this.settings, additionalSettings, additionalSettingsFilter);

final List<SettingUpgrader<?>> settingsUpgraders = pluginsService.filterPlugins(Plugin.class)
.stream()
.map(Plugin::getSettingUpgraders)
.flatMap(List::stream)
.collect(Collectors.toList());

final SettingsModule settingsModule =
new SettingsModule(this.settings, additionalSettings, additionalSettingsFilter, settingsUpgraders);
scriptModule.registerClusterSettingsListeners(settingsModule.getClusterSettings());
resourcesToClose.add(resourceWatcherService);
final NetworkService networkService = new NetworkService(
Expand Down
10 changes: 10 additions & 0 deletions server/src/main/java/org/elasticsearch/plugins/Plugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.SettingUpgrader;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsModule;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
Expand Down Expand Up @@ -172,6 +173,15 @@ public void onIndexModule(IndexModule indexModule) {}
*/
public List<String> getSettingsFilter() { return Collections.emptyList(); }

/**
* Get the setting upgraders provided by this plugin.
*
* @return the settings upgraders
*/
public List<SettingUpgrader<?>> getSettingUpgraders() {
return Collections.emptyList();
}

/**
* Provides a function to modify global custom meta data on startup.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
import java.util.Collections;
import java.util.concurrent.TimeUnit;

import static java.util.Collections.emptyList;

public class GetIndexActionTests extends ESSingleNodeTestCase {

private TransportService transportService;
Expand All @@ -58,7 +60,7 @@ public class GetIndexActionTests extends ESSingleNodeTestCase {
public void setUp() throws Exception {
super.setUp();

settingsFilter = new SettingsModule(Settings.EMPTY, Collections.emptyList(), Collections.emptyList()).getSettingsFilter();
settingsFilter = new SettingsModule(Settings.EMPTY, emptyList(), emptyList(), emptyList()).getSettingsFilter();
threadPool = new TestThreadPool("GetIndexActionTests");
clusterService = getInstanceFromNode(ClusterService.class);
indicesService = getInstanceFromNode(IndicesService.class);
Expand Down
Loading