Skip to content

Commit ee0bb73

Browse files
authored
Avoid updating settings version in MetadataMigrateToDataStreamService when settings have not changed (#118704) (#118706)
If the input index already has the `index.hidden` setting set to `true`, MetadataMigrateToDataStreamService::prepareBackingIndex can incorrectly increment the settings version even if it does not change the settings. This results in an assertion failure in IndexService::updateMetadata that will take down a node if assertions are enabled. This fixes that, only incrementing the settings version if the settings actually changed.
1 parent d68d355 commit ee0bb73

File tree

3 files changed

+94
-3
lines changed

3 files changed

+94
-3
lines changed

docs/changelog/118704.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 118704
2+
summary: Avoid updating settings version in `MetadataMigrateToDataStreamService` when
3+
settings have not changed
4+
area: Data streams
5+
type: bug
6+
issues: []

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.elasticsearch.core.SuppressForbidden;
3030
import org.elasticsearch.core.TimeValue;
3131
import org.elasticsearch.index.Index;
32+
import org.elasticsearch.index.IndexSettings;
3233
import org.elasticsearch.index.IndexVersion;
3334
import org.elasticsearch.index.mapper.DataStreamTimestampFieldMapper;
3435
import org.elasticsearch.index.mapper.DocumentMapper;
@@ -250,9 +251,11 @@ static void prepareBackingIndex(
250251
DataStreamFailureStoreDefinition.applyFailureStoreSettings(nodeSettings, settingsUpdate);
251252
}
252253

253-
imb.settings(settingsUpdate.build())
254-
.settingsVersion(im.getSettingsVersion() + 1)
255-
.mappingVersion(im.getMappingVersion() + 1)
254+
Settings maybeUpdatedSettings = settingsUpdate.build();
255+
if (IndexSettings.same(im.getSettings(), maybeUpdatedSettings) == false) {
256+
imb.settings(maybeUpdatedSettings).settingsVersion(im.getSettingsVersion() + 1);
257+
}
258+
imb.mappingVersion(im.getMappingVersion() + 1)
256259
.mappingsUpdatedVersion(IndexVersion.current())
257260
.putMapping(new MappingMetadata(mapper));
258261
b.put(imb);

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

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424
import java.io.IOException;
2525
import java.util.List;
2626
import java.util.Set;
27+
import java.util.function.Function;
2728

2829
import static org.elasticsearch.cluster.metadata.DataStreamTestHelper.generateMapping;
2930
import static org.hamcrest.Matchers.containsInAnyOrder;
3031
import static org.hamcrest.Matchers.containsString;
3132
import static org.hamcrest.Matchers.equalTo;
33+
import static org.hamcrest.Matchers.not;
3234
import static org.hamcrest.Matchers.notNullValue;
3335
import static org.mockito.Mockito.mock;
3436
import static org.mockito.Mockito.when;
@@ -425,6 +427,86 @@ public void testCreateDataStreamWithoutSuppliedWriteIndex() {
425427
assertThat(e.getMessage(), containsString("alias [" + dataStreamName + "] must specify a write index"));
426428
}
427429

430+
public void testSettingsVersion() throws IOException {
431+
/*
432+
* This tests that applyFailureStoreSettings updates the settings version when the settings have been modified, and does not change
433+
* it otherwise. Incrementing the settings version when the settings have not changed can result in an assertion failing in
434+
* IndexService::updateMetadata.
435+
*/
436+
String indexName = randomAlphaOfLength(30);
437+
String dataStreamName = randomAlphaOfLength(50);
438+
Function<IndexMetadata, MapperService> mapperSupplier = this::getMapperService;
439+
boolean removeAlias = randomBoolean();
440+
boolean failureStore = randomBoolean();
441+
Settings nodeSettings = Settings.EMPTY;
442+
443+
{
444+
/*
445+
* Here the input indexMetadata will have the index.hidden setting set to true. So we expect no change to the settings, and
446+
* for the settings version to remain the same
447+
*/
448+
Metadata.Builder metadataBuilder = Metadata.builder();
449+
Settings indexMetadataSettings = Settings.builder()
450+
.put(IndexMetadata.SETTING_INDEX_HIDDEN, true)
451+
.put(IndexMetadata.SETTING_VERSION_CREATED, IndexVersion.current())
452+
.build();
453+
IndexMetadata indexMetadata = IndexMetadata.builder(indexName)
454+
.settings(indexMetadataSettings)
455+
.numberOfShards(1)
456+
.numberOfReplicas(0)
457+
.putMapping(getTestMappingWithTimestamp())
458+
.build();
459+
MetadataMigrateToDataStreamService.prepareBackingIndex(
460+
metadataBuilder,
461+
indexMetadata,
462+
dataStreamName,
463+
mapperSupplier,
464+
removeAlias,
465+
failureStore,
466+
nodeSettings
467+
);
468+
Metadata metadata = metadataBuilder.build();
469+
assertThat(indexMetadata.getSettings(), equalTo(metadata.index(indexName).getSettings()));
470+
assertThat(metadata.index(indexName).getSettingsVersion(), equalTo(indexMetadata.getSettingsVersion()));
471+
}
472+
{
473+
/*
474+
* Here the input indexMetadata will not have the index.hidden setting set to true. So prepareBackingIndex will add that,
475+
* meaning that the settings and settings version will change.
476+
*/
477+
Metadata.Builder metadataBuilder = Metadata.builder();
478+
Settings indexMetadataSettings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, IndexVersion.current()).build();
479+
IndexMetadata indexMetadata = IndexMetadata.builder(indexName)
480+
.settings(indexMetadataSettings)
481+
.numberOfShards(1)
482+
.numberOfReplicas(0)
483+
.putMapping(getTestMappingWithTimestamp())
484+
.build();
485+
MetadataMigrateToDataStreamService.prepareBackingIndex(
486+
metadataBuilder,
487+
indexMetadata,
488+
dataStreamName,
489+
mapperSupplier,
490+
removeAlias,
491+
failureStore,
492+
nodeSettings
493+
);
494+
Metadata metadata = metadataBuilder.build();
495+
assertThat(indexMetadata.getSettings(), not(equalTo(metadata.index(indexName).getSettings())));
496+
assertThat(metadata.index(indexName).getSettingsVersion(), equalTo(indexMetadata.getSettingsVersion() + 1));
497+
}
498+
}
499+
500+
private String getTestMappingWithTimestamp() {
501+
return """
502+
{
503+
"properties": {
504+
"@timestamp": {"type": "date"}
505+
}
506+
}
507+
""";
508+
}
509+
428510
private MapperService getMapperService(IndexMetadata im) {
429511
try {
430512
return createMapperService("{\"_doc\": " + im.mapping().source().toString() + "}");

0 commit comments

Comments
 (0)