Skip to content

Commit 09fc320

Browse files
authored
Re-define index.mapper.dynamic setting in 8.x (#109341)
Currently when upgrading a 7.x cluster to 8.x with `index.mapper.dynamic` index setting defined the following happens: - In case of a full cluster restart upgrade, then the index setting gets archived and after the upgrade the cluster is in a green health. - In case of a rolling cluster restart upgrade, then shards of indices with the index setting fail to allocate as nodes start with 8.x version. The result is that the cluster has a red health and the index setting isn't archived. Closing and opening the index should archive the index setting and allocate the shards. The change is about ensuring the same behavior happens when upgrading a cluster from 7.x to 8.x with indices that have the `index.mapper.dynamic` index setting defined. By re-defining the `index.mapper.dynamic `index setting with `IndexSettingDeprecatedInV7AndRemovedInV8` property, the index is allowed to exist in 7.x indices, but can't be defined in new indices after the upgrade. This way we don't have to rely on index archiving and upgrading via full cluster restart or rolling restart will yield the same outcome. Based on the test in #109301. Relates to #109160 and #96075
1 parent f75afb0 commit 09fc320

File tree

5 files changed

+136
-0
lines changed

5 files changed

+136
-0
lines changed

docs/changelog/109341.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 109341
2+
summary: Re-define `index.mapper.dynamic` setting in 8.x for a better 7.x to 8.x upgrade if this setting is used.
3+
area: Mapping
4+
type: bug
5+
issues: []
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.upgrades;
10+
11+
import com.carrotsearch.randomizedtesting.annotations.Name;
12+
13+
import org.elasticsearch.client.Request;
14+
import org.elasticsearch.client.ResponseException;
15+
import org.elasticsearch.common.settings.Settings;
16+
import org.elasticsearch.common.xcontent.support.XContentMapValues;
17+
import org.elasticsearch.test.cluster.ElasticsearchCluster;
18+
import org.elasticsearch.test.cluster.FeatureFlag;
19+
import org.elasticsearch.test.cluster.local.LocalClusterConfigProvider;
20+
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
21+
import org.junit.ClassRule;
22+
23+
import java.io.IOException;
24+
25+
import static org.hamcrest.Matchers.containsString;
26+
import static org.hamcrest.Matchers.equalTo;
27+
28+
public class UpgradeWithOldIndexSettingsIT extends ParameterizedFullClusterRestartTestCase {
29+
30+
protected static LocalClusterConfigProvider clusterConfig = c -> {};
31+
32+
@ClassRule
33+
public static ElasticsearchCluster cluster = ElasticsearchCluster.local()
34+
.distribution(DistributionType.DEFAULT)
35+
.version(getOldClusterTestVersion())
36+
.nodes(2)
37+
.setting("xpack.security.enabled", "false")
38+
.feature(FeatureFlag.FAILURE_STORE_ENABLED)
39+
.apply(() -> clusterConfig)
40+
.build();
41+
42+
@Override
43+
protected ElasticsearchCluster getUpgradeCluster() {
44+
return cluster;
45+
}
46+
47+
public UpgradeWithOldIndexSettingsIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) {
48+
super(upgradeStatus);
49+
}
50+
51+
public void testMapperDynamicIndexSetting() throws IOException {
52+
assumeTrue(
53+
"Setting deprecated in 6.x, but remained in 7.x and is no longer defined in 8.x",
54+
getOldClusterTestVersion().before("8.0.0")
55+
);
56+
String indexName = "my-index";
57+
if (isRunningAgainstOldCluster()) {
58+
createIndex(indexName);
59+
60+
var request = new Request("PUT", "/my-index/_settings");
61+
request.setJsonEntity(org.elasticsearch.common.Strings.toString(Settings.builder().put("index.mapper.dynamic", true).build()));
62+
request.setOptions(
63+
expectWarnings(
64+
"[index.mapper.dynamic] setting was deprecated in Elasticsearch and will be removed in a future release! "
65+
+ "See the breaking changes documentation for the next major version."
66+
)
67+
);
68+
assertOK(client().performRequest(request));
69+
} else {
70+
var indexSettings = getIndexSettings(indexName);
71+
assertThat(XContentMapValues.extractValue(indexName + ".settings.index.mapper.dynamic", indexSettings), equalTo("true"));
72+
ensureGreen(indexName);
73+
// New indices can never define the index.mapper.dynamic setting.
74+
Exception e = expectThrows(
75+
ResponseException.class,
76+
() -> createIndex("my-index2", Settings.builder().put("index.mapper.dynamic", true).build())
77+
);
78+
assertThat(e.getMessage(), containsString("unknown setting [index.mapper.dynamic]"));
79+
}
80+
}
81+
82+
}

qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/UpgradeWithOldIndexSettingsIT.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.Map;
2323

2424
import static org.elasticsearch.rest.action.search.RestSearchAction.TOTAL_HITS_AS_INT_PARAM;
25+
import static org.hamcrest.Matchers.containsString;
26+
import static org.hamcrest.Matchers.equalTo;
2527
import static org.hamcrest.Matchers.is;
2628

2729
public class UpgradeWithOldIndexSettingsIT extends AbstractRollingUpgradeTestCase {
@@ -102,6 +104,38 @@ public void testOldIndexSettings() throws Exception {
102104
}
103105
}
104106

107+
public void testMapperDynamicIndexSetting() throws IOException {
108+
assumeTrue(
109+
"Setting deprecated in 6.x, but remained in 7.x and is no longer defined in 8.x",
110+
getOldClusterTestVersion().before("8.0.0")
111+
);
112+
String indexName = "my-index";
113+
if (isOldCluster()) {
114+
createIndex(indexName);
115+
Request request = new Request("PUT", "/" + indexName + "/_settings");
116+
request.setJsonEntity(org.elasticsearch.common.Strings.toString(Settings.builder().put("index.mapper.dynamic", true).build()));
117+
request.setOptions(
118+
expectWarnings(
119+
"[index.mapper.dynamic] setting was deprecated in Elasticsearch and will be removed in a future release! "
120+
+ "See the breaking changes documentation for the next major version."
121+
)
122+
);
123+
assertOK(client().performRequest(request));
124+
} else {
125+
if (isUpgradedCluster()) {
126+
var indexSettings = getIndexSettings(indexName);
127+
assertThat(XContentMapValues.extractValue(indexName + ".settings.index.mapper.dynamic", indexSettings), equalTo("true"));
128+
ensureGreen(indexName);
129+
// New indices can never define the index.mapper.dynamic setting.
130+
Exception e = expectThrows(
131+
ResponseException.class,
132+
() -> createIndex("my-index2", Settings.builder().put("index.mapper.dynamic", true).build())
133+
);
134+
assertThat(e.getMessage(), containsString("unknown setting [index.mapper.dynamic]"));
135+
}
136+
}
137+
}
138+
105139
private void assertCount(String index, int countAtLeast) throws IOException {
106140
Request searchTestIndexRequest = new Request("POST", "/" + index + "/_search");
107141
searchTestIndexRequest.addParameter(TOTAL_HITS_AS_INT_PARAM, "true");

server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings {
158158
MapperService.INDEX_MAPPING_DEPTH_LIMIT_SETTING,
159159
MapperService.INDEX_MAPPING_DIMENSION_FIELDS_LIMIT_SETTING,
160160
MapperService.INDEX_MAPPING_FIELD_NAME_LENGTH_LIMIT_SETTING,
161+
MapperService.INDEX_MAPPER_DYNAMIC_SETTING,
161162
BitsetFilterCache.INDEX_LOAD_RANDOM_ACCESS_FILTERS_EAGERLY_SETTING,
162163
IndexModule.INDEX_STORE_TYPE_SETTING,
163164
IndexModule.INDEX_STORE_PRE_LOAD_SETTING,

server/src/main/java/org/elasticsearch/index/mapper/MapperService.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
2222
import org.elasticsearch.common.xcontent.XContentHelper;
2323
import org.elasticsearch.core.Nullable;
24+
import org.elasticsearch.core.UpdateForV9;
2425
import org.elasticsearch.index.AbstractIndexComponent;
2526
import org.elasticsearch.index.IndexSettings;
2627
import org.elasticsearch.index.IndexVersion;
@@ -147,6 +148,19 @@ public boolean isAutoUpdate() {
147148
Property.Dynamic,
148149
Property.IndexScope
149150
);
151+
/**
152+
* Legacy index setting, kept for 7.x BWC compatibility. This setting has no effect in 8.x. Do not use.
153+
* TODO: Remove in 9.0
154+
*/
155+
@Deprecated
156+
@UpdateForV9
157+
public static final Setting<Boolean> INDEX_MAPPER_DYNAMIC_SETTING = Setting.boolSetting(
158+
"index.mapper.dynamic",
159+
true,
160+
Property.Dynamic,
161+
Property.IndexScope,
162+
Property.IndexSettingDeprecatedInV7AndRemovedInV8
163+
);
150164

151165
private final IndexAnalyzers indexAnalyzers;
152166
private final MappingParser mappingParser;

0 commit comments

Comments
 (0)