Skip to content

Commit cd7a93b

Browse files
Fix corrupted Metadata from index and alias having the same name (elastic#91456)
This fixes a bug introduced in elastic#87863 which added a Metadata copy constructor with separate name collision checks that assumed index name and alias names were already validated in `IndexMetada`. => fixed corrupted states by actually adding the validation to `IndexMetadata` to make it impossible to instantiate a broken `IndexMetadata` in the first place.
1 parent 784d892 commit cd7a93b

File tree

5 files changed

+41
-22
lines changed

5 files changed

+41
-22
lines changed

docs/changelog/91456.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 91456
2+
summary: Fix corrupted Metadata from index and alias having the same name
3+
area: Cluster Coordination
4+
type: bug
5+
issues: []

server/src/internalClusterTest/java/org/elasticsearch/aliases/IndexAliasesIT.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,15 @@ public void testIndexingAndQueryingHiddenAliases() throws Exception {
13761376
assertThat(searchResponse.getHits().getHits(), emptyArray());
13771377
}
13781378

1379+
public void testCreateIndexAndAliasWithSameNameFails() {
1380+
final String indexName = "index-name";
1381+
final IllegalArgumentException iae = expectThrows(
1382+
IllegalArgumentException.class,
1383+
() -> client().admin().indices().prepareCreate(indexName).addAlias(new Alias(indexName)).execute().actionGet()
1384+
);
1385+
assertEquals("alias name [" + indexName + "] self-conflicts with index name", iae.getMessage());
1386+
}
1387+
13791388
public void testGetAliasAndAliasExistsForHiddenAliases() {
13801389
final String writeIndex = randomAlphaOfLength(5).toLowerCase(Locale.ROOT);
13811390
final String nonWriteIndex = randomAlphaOfLength(6).toLowerCase(Locale.ROOT);

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2017,6 +2017,13 @@ public IndexMetadata build() {
20172017
lifecycleExecutionState = LifecycleExecutionState.EMPTY_STATE;
20182018
}
20192019

2020+
var aliasesMap = aliases.build();
2021+
for (AliasMetadata alias : aliasesMap.values()) {
2022+
if (alias.alias().equals(index)) {
2023+
throw new IllegalArgumentException("alias name [" + index + "] self-conflicts with index name");
2024+
}
2025+
}
2026+
20202027
final boolean isSearchableSnapshot = SearchableSnapshotsSettings.isSearchableSnapshotStore(settings);
20212028
final String indexMode = settings.get(IndexSettings.MODE.getKey());
20222029
final boolean isTsdb = indexMode != null && IndexMode.TIME_SERIES.getName().equals(indexMode.toLowerCase(Locale.ROOT));
@@ -2032,7 +2039,7 @@ public IndexMetadata build() {
20322039
numberOfReplicas,
20332040
settings,
20342041
mapping,
2035-
aliases.build(),
2042+
aliasesMap,
20362043
newCustomMetadata,
20372044
Map.ofEntries(denseInSyncAllocationIds),
20382045
requireFilters,

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,19 @@ public void testLifeCyclePolicyName() {
482482
assertThat(idxMeta2.getLifecyclePolicyName(), equalTo("some_policy"));
483483
}
484484

485+
public void testIndexAndAliasWithSameName() {
486+
final IllegalArgumentException iae = expectThrows(
487+
IllegalArgumentException.class,
488+
() -> IndexMetadata.builder("index")
489+
.settings(Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT))
490+
.numberOfShards(1)
491+
.numberOfReplicas(0)
492+
.putAlias(AliasMetadata.builder("index").build())
493+
.build()
494+
);
495+
assertEquals("alias name [index] self-conflicts with index name", iae.getMessage());
496+
}
497+
485498
private static Settings indexSettingsWithDataTier(String dataTier) {
486499
return Settings.builder()
487500
.put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT)

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

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -193,26 +193,6 @@ public void testFindAliasWithExclusionAndOverride() {
193193
assertThat(aliases.get(1).alias(), equalTo("bb"));
194194
}
195195

196-
public void testIndexAndAliasWithSameName() {
197-
IndexMetadata.Builder builder = IndexMetadata.builder("index")
198-
.settings(Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT))
199-
.numberOfShards(1)
200-
.numberOfReplicas(0)
201-
.putAlias(AliasMetadata.builder("index").build());
202-
try {
203-
Metadata.builder().put(builder).build();
204-
fail("exception should have been thrown");
205-
} catch (IllegalStateException e) {
206-
assertThat(
207-
e.getMessage(),
208-
equalTo(
209-
"index, alias, and data stream names need to be unique, but the following duplicates were found [index (alias "
210-
+ "of [index]) conflicts with index]"
211-
)
212-
);
213-
}
214-
}
215-
216196
public void testAliasCollidingWithAnExistingIndex() {
217197
int indexCount = randomIntBetween(10, 100);
218198
Set<String> indices = Sets.newHashSetWithExpectedSize(indexCount);
@@ -221,7 +201,12 @@ public void testAliasCollidingWithAnExistingIndex() {
221201
}
222202
Map<String, Set<String>> aliasToIndices = new HashMap<>();
223203
for (String alias : randomSubsetOf(randomIntBetween(1, 10), indices)) {
224-
aliasToIndices.put(alias, new HashSet<>(randomSubsetOf(randomIntBetween(1, 3), indices)));
204+
Set<String> indicesInAlias;
205+
do {
206+
indicesInAlias = new HashSet<>(randomSubsetOf(randomIntBetween(1, 3), indices));
207+
indicesInAlias.remove(alias);
208+
} while (indicesInAlias.isEmpty());
209+
aliasToIndices.put(alias, indicesInAlias);
225210
}
226211
int properAliases = randomIntBetween(0, 3);
227212
for (int i = 0; i < properAliases; i++) {

0 commit comments

Comments
 (0)