Skip to content

Commit dafdbea

Browse files
committed
Do not ignore request analysis/similarity on resize (#30216)
Today when a resize operation is performed, we copy the analysis, similarity, and sort settings from the source index. It is possible for the resize request to include additional index settings including analysis, similarity, and sort settings. We reject sort settings when validating the request. However, we silently ignore analysis and similarity settings on the request that are already set on the source index. Since it is possible to change the analysis and similarity settings on an existing index, this should be considered a bug and the sort of leniency that we abhor. This commit addresses this bug by allowing the request analysis/similarity settings to override the existing analysis/similarity settings on the target.
1 parent 2e60abb commit dafdbea

File tree

5 files changed

+74
-20
lines changed

5 files changed

+74
-20
lines changed

docs/CHANGELOG.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ written to by an older Elasticsearch after writing to it with a newer Elasticsea
3939

4040
=== Bug Fixes
4141

42+
Do not ignore request analysis/similarity settings on index resize operations when the source index already contains such settings ({pull}30216[#30216])
43+
4244
=== Regressions
4345

4446
=== Known Issues

docs/reference/indices/shrink-index.asciidoc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,10 @@ POST my_source_index/_shrink/my_target_index
119119
segment.
120120

121121

122-
NOTE: Mappings may not be specified in the `_shrink` request, and all
123-
`index.analysis.*` and `index.similarity.*` settings will be overwritten with
124-
the settings from the source index.
122+
NOTE: Mappings may not be specified in the `_shrink` request.
123+
124+
NOTE: By default, with the exception of `index.analysis`, `index.similarity`, and `index.sort` settings, index settings on the source
125+
index are not copied during a shrink operation.
125126

126127
[float]
127128
=== Monitoring the shrink process

docs/reference/indices/split-index.asciidoc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,10 @@ POST my_source_index/_split/my_target_index
169169
number of shards in the source index.
170170

171171

172-
NOTE: Mappings may not be specified in the `_split` request, and all
173-
`index.analysis.*` and `index.similarity.*` settings will be overwritten with
174-
the settings from the source index.
172+
NOTE: Mappings may not be specified in the `_split` request.
173+
174+
NOTE: By default, with the exception of `index.analysis`, `index.similarity`, and `index.sort` settings, index settings on the source
175+
index are not copied during a shrink operation.
175176

176177
[float]
177178
=== Monitoring the split process

server/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import org.elasticsearch.common.logging.Loggers;
6262
import org.elasticsearch.common.regex.Regex;
6363
import org.elasticsearch.common.settings.IndexScopedSettings;
64+
import org.elasticsearch.common.settings.Setting;
6465
import org.elasticsearch.common.settings.Settings;
6566
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
6667
import org.elasticsearch.common.xcontent.XContentHelper;
@@ -693,8 +694,13 @@ static void prepareResizeIndexSettings(ClusterState currentState, Set<String> ma
693694
throw new IllegalStateException("unknown resize type is " + type);
694695
}
695696

696-
final Predicate<String> sourceSettingsPredicate = (s) -> s.startsWith("index.similarity.")
697-
|| s.startsWith("index.analysis.") || s.startsWith("index.sort.") || s.equals("index.mapping.single_type");
697+
final Predicate<String> sourceSettingsPredicate =
698+
(s) -> (
699+
s.startsWith("index.similarity.")
700+
|| s.startsWith("index.analysis.")
701+
|| s.startsWith("index.sort.")
702+
|| s.equals("index.mapping.single_type"))
703+
&& indexSettingsBuilder.keys().contains(s) == false;
698704
indexSettingsBuilder
699705
// now copy all similarity / analysis / sort / single_type settings - this overrides all settings from the user unless they
700706
// wanna add extra settings

server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexServiceTests.java

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import static java.util.Collections.emptyMap;
5353
import static java.util.Collections.min;
5454
import static org.hamcrest.Matchers.endsWith;
55+
import static org.hamcrest.Matchers.equalTo;
5556

5657
public class MetaDataCreateIndexServiceTests extends ESTestCase {
5758

@@ -244,7 +245,7 @@ public void testResizeIndexSettings() {
244245
.put("index.version.created", version)
245246
.put("index.version.upgraded", upgraded)
246247
.put("index.version.minimum_compatible", minCompat.luceneVersion.toString())
247-
.put("index.analysis.analyzer.my_analyzer.tokenizer", "keyword")
248+
.put("index.analysis.analyzer.default.tokenizer", "keyword")
248249
.build())).nodes(DiscoveryNodes.builder().add(newNode("node1")))
249250
.build();
250251
AllocationService service = new AllocationService(Settings.builder().build(), new AllocationDeciders(Settings.EMPTY,
@@ -258,17 +259,60 @@ public void testResizeIndexSettings() {
258259
routingTable.index(indexName).shardsWithState(ShardRoutingState.INITIALIZING)).routingTable();
259260
clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build();
260261

261-
Settings.Builder builder = Settings.builder();
262-
builder.put("index.number_of_shards", 1);
263-
MetaDataCreateIndexService.prepareResizeIndexSettings(clusterState, Collections.emptySet(), builder,
264-
clusterState.metaData().index(indexName).getIndex(), "target", ResizeType.SHRINK);
265-
assertEquals("similarity settings must be copied", "BM25", builder.build().get("index.similarity.default.type"));
266-
assertEquals("analysis settings must be copied",
267-
"keyword", builder.build().get("index.analysis.analyzer.my_analyzer.tokenizer"));
268-
assertEquals("node1", builder.build().get("index.routing.allocation.initial_recovery._id"));
269-
assertEquals("1", builder.build().get("index.allocation.max_retries"));
270-
assertEquals(version, builder.build().getAsVersion("index.version.created", null));
271-
assertEquals(upgraded, builder.build().getAsVersion("index.version.upgraded", null));
262+
{
263+
final Settings.Builder builder = Settings.builder();
264+
builder.put("index.number_of_shards", 1);
265+
MetaDataCreateIndexService.prepareResizeIndexSettings(
266+
clusterState,
267+
Collections.emptySet(),
268+
builder,
269+
clusterState.metaData().index(indexName).getIndex(),
270+
"target",
271+
ResizeType.SHRINK);
272+
final Settings settings = builder.build();
273+
assertThat("similarity settings must be copied", settings.get("index.similarity.default.type"), equalTo("BM25"));
274+
assertThat(
275+
"analysis settings must be copied", settings.get("index.analysis.analyzer.default.tokenizer"), equalTo("keyword"));
276+
assertThat(settings.get("index.routing.allocation.initial_recovery._id"), equalTo("node1"));
277+
assertThat(settings.get("index.allocation.max_retries"), equalTo("1"));
278+
assertThat(settings.getAsVersion("index.version.created", null), equalTo(version));
279+
assertThat(settings.getAsVersion("index.version.upgraded", null), equalTo(upgraded));
280+
}
281+
282+
// analysis settings from the request are not overwritten
283+
{
284+
final Settings.Builder builder = Settings.builder();
285+
builder.put("index.number_of_shards", 1);
286+
builder.put("index.analysis.analyzer.default.tokenizer", "whitespace");
287+
MetaDataCreateIndexService.prepareResizeIndexSettings(
288+
clusterState,
289+
Collections.emptySet(),
290+
builder,
291+
clusterState.metaData().index(indexName).getIndex(),
292+
"target",
293+
ResizeType.SHRINK);
294+
final Settings settings = builder.build();
295+
assertThat(
296+
"analysis settings are not overwritten",
297+
settings.get("index.analysis.analyzer.default.tokenizer"),
298+
equalTo("whitespace"));
299+
}
300+
301+
// similarity settings from the request are not overwritten
302+
{
303+
final Settings.Builder builder = Settings.builder();
304+
builder.put("index.number_of_shards", 1);
305+
builder.put("index.similarity.default.type", "DFR");
306+
MetaDataCreateIndexService.prepareResizeIndexSettings(
307+
clusterState,
308+
Collections.emptySet(),
309+
builder,
310+
clusterState.metaData().index(indexName).getIndex(),
311+
"target",
312+
ResizeType.SHRINK);
313+
final Settings settings = builder.build();
314+
assertThat("similarity settings are not overwritten", settings.get("index.similarity.default.type"), equalTo("DFR"));
315+
}
272316
}
273317

274318
private DiscoveryNode newNode(String nodeId) {

0 commit comments

Comments
 (0)