org.elasticsearch.cluster.desirednodes.DesiredNodesSettingsValidator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch subproject :server
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.cluster.desirednodes;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.DesiredNode;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.core.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
import static java.lang.String.format;
import static org.elasticsearch.common.util.concurrent.EsExecutors.NODE_PROCESSORS_SETTING;
public class DesiredNodesSettingsValidator {
private record DesiredNodeValidationError(int position, @Nullable String externalId, RuntimeException exception) {}
private final ClusterSettings clusterSettings;
public DesiredNodesSettingsValidator(ClusterSettings clusterSettings) {
this.clusterSettings = clusterSettings;
}
public void validate(List nodes) {
final List validationErrors = new ArrayList<>();
for (int i = 0; i < nodes.size(); i++) {
final DesiredNode node = nodes.get(i);
try {
validate(node);
} catch (IllegalArgumentException e) {
validationErrors.add(new DesiredNodeValidationError(i, node.externalId(), e));
}
}
if (validationErrors.isEmpty() == false) {
final String nodeIndicesWithFailures = validationErrors.stream()
.map(DesiredNodeValidationError::position)
.map(i -> Integer.toString(i))
.collect(Collectors.joining(","));
final String nodeIdsWithFailures = validationErrors.stream()
.map(DesiredNodeValidationError::externalId)
.collect(Collectors.joining(","));
IllegalArgumentException invalidSettingsException = new IllegalArgumentException(
format(
Locale.ROOT,
"Nodes with ids [%s] in positions [%s] contain invalid settings",
nodeIdsWithFailures,
nodeIndicesWithFailures
)
);
for (DesiredNodeValidationError exceptionTuple : validationErrors) {
invalidSettingsException.addSuppressed(exceptionTuple.exception);
}
throw invalidSettingsException;
}
}
private void validate(DesiredNode node) {
if (node.version().before(Version.CURRENT)) {
throw new IllegalArgumentException(
format(Locale.ROOT, "Illegal node version [%s]. Only [%s] or newer versions are supported", node.version(), Version.CURRENT)
);
}
// Validating settings for future versions can be unsafe:
// - If the legal range is upgraded in the newer version
// - If a new setting is used as the default value for a previous setting
// To avoid considering these as invalid settings,
// We just don't validate settings for versions in newer versions.
if (node.version().after(Version.CURRENT)) {
return;
}
Settings settings = node.settings();
// node.processors rely on the environment to define its ranges, in this case
// we create a new setting just to run the validations using the desired node
// number of available processors
if (settings.hasValue(NODE_PROCESSORS_SETTING.getKey())) {
int minProcessors = node.roundedDownMinProcessors();
Integer roundedUpMaxProcessors = node.roundedUpMaxProcessors();
int maxProcessors = roundedUpMaxProcessors == null ? minProcessors : roundedUpMaxProcessors;
Setting.doubleSetting(
NODE_PROCESSORS_SETTING.getKey(),
minProcessors,
Double.MIN_VALUE,
maxProcessors,
Setting.Property.NodeScope
).get(settings);
final Settings.Builder updatedSettings = Settings.builder().put(settings);
updatedSettings.remove(NODE_PROCESSORS_SETTING.getKey());
settings = updatedSettings.build();
}
clusterSettings.validate(settings, true);
}
}