Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public enum ReferenceDocs {
SECURE_SETTINGS,
CLUSTER_SHARD_LIMIT,
DELETE_INDEX_BLOCK,
ARCHIVED_SETTINGS,
// this comment keeps the ';' on the next line so every entry above has a trailing ',' which makes the diff for adding new links cleaner
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import org.apache.lucene.search.spell.LevenshteinDistance;
import org.apache.lucene.util.CollectionUtil;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.common.ReferenceDocs;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.util.Maps;
import org.elasticsearch.common.util.set.Sets;
Expand Down Expand Up @@ -543,29 +545,40 @@ void validate(final String key, final Settings settings, final boolean validateV
void validate(final String key, final Settings settings, final boolean validateValue, final boolean validateInternalOrPrivateIndex) {
Setting<?> setting = getRaw(key);
if (setting == null) {
LevenshteinDistance ld = new LevenshteinDistance();
List<Tuple<Float, String>> scoredKeys = new ArrayList<>();
for (String k : this.keySettings.keySet()) {
float distance = ld.getDistance(key, k);
if (distance > 0.7f) {
scoredKeys.add(new Tuple<>(distance, k));
}
}
CollectionUtil.timSort(scoredKeys, (a, b) -> b.v1().compareTo(a.v1()));
String msgPrefix = "unknown setting";
SecureSettings secureSettings = settings.getSecureSettings();
if (secureSettings != null && settings.getSecureSettings().getSettingNames().contains(key)) {
msgPrefix = "unknown secure setting";
String msgPrefix = (secureSettings != null && secureSettings.getSettingNames().contains(key))
? "unknown secure setting"
: "unknown setting";
if (key.startsWith(ARCHIVED_SETTINGS_PREFIX)) {
throw new IllegalArgumentException(
Strings.format(
"%s [%s] was archived after upgrading, and must be removed. See [%s] for details.",
msgPrefix,
key,
ReferenceDocs.ARCHIVED_SETTINGS
)
);
}
String msg = msgPrefix + " [" + key + "]";
List<String> keys = scoredKeys.stream().map((a) -> a.v2()).toList();
List<String> keys = findSimilarKeys(key);
if (keys.isEmpty() == false) {
msg += " did you mean " + (keys.size() == 1 ? "[" + keys.get(0) + "]" : "any of " + keys.toString()) + "?";
throw new IllegalArgumentException(
Strings.format(
"%s [%s] did you mean %s?",
msgPrefix,
key,
(keys.size() == 1 ? "[" + keys.get(0) + "]" : "any of " + keys)
)
);
} else {
msg += " please check that any required plugins are installed, or check the breaking changes documentation for removed "
+ "settings";
throw new IllegalArgumentException(
Strings.format(
"%s [%s] please check that any required plugins are installed,"
+ " or check the breaking changes documentation for removed settings",
msgPrefix,
key
)
);
}
throw new IllegalArgumentException(msg);
} else {
Set<Setting.SettingDependency> settingsDependencies = setting.getSettingsDependencies(key);
if (setting.hasComplexMatcher()) {
Expand Down Expand Up @@ -609,6 +622,19 @@ void validate(final String key, final Settings settings, final boolean validateV
}
}

private List<String> findSimilarKeys(String key) {
LevenshteinDistance ld = new LevenshteinDistance();
List<Tuple<Float, String>> scoredKeys = new ArrayList<>();
for (String k : this.keySettings.keySet()) {
float distance = ld.getDistance(key, k);
if (distance > 0.7f) {
scoredKeys.add(new Tuple<>(distance, k));
}
}
CollectionUtil.timSort(scoredKeys, (a, b) -> b.v1().compareTo(a.v1()));
return scoredKeys.stream().map((a) -> a.v2()).toList();
}

/**
* Transactional interface to update settings.
* @see Setting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ ALLOCATION_EXPLAIN_MAX_RETRY cluster-allocati
SECURE_SETTINGS secure-settings.html
CLUSTER_SHARD_LIMIT misc-cluster-settings.html#cluster-shard-limit
DELETE_INDEX_BLOCK api/doc/elasticsearch/operation/operation-indices-remove-block
ARCHIVED_SETTINGS deploy-manage/upgrade/deployment-or-cluster/archived-settings
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,24 @@ public Iterator<Setting<?>> settings() {
assertThat(e3.getMessage(), equalTo("too long"));
}

public void testValidateArchivedSetting() {
IndexScopedSettings settings = new IndexScopedSettings(Settings.EMPTY, IndexScopedSettings.BUILT_IN_INDEX_SETTINGS);
final IllegalArgumentException e = expectThrows(
IllegalArgumentException.class,
() -> settings.validate(Settings.builder().put("archived.index.store.type", "boom").build(), false)
);
assertThat(
e.getMessage(),
equalTo(
"unknown setting [archived.index.store.type] was archived after upgrading, and must be removed."
+ " See [https://www.elastic.co/guide/en/elasticsearch/reference/8.19/"
+ "deploy-manage/upgrade/deployment-or-cluster/archived-settings] "
+ "for details."
)
);

}

public void testTupleAffixUpdateConsumer() {
String prefix = randomAlphaOfLength(3) + "foo.";
String intSuffix = randomAlphaOfLength(3);
Expand Down