From cddb119f180a41398bb9f96af998df9efaa2071d Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Wed, 9 Nov 2022 16:12:42 +0100 Subject: [PATCH 1/2] Fix corrupted Metadata from index and alias having the same name (#91456) This fixes a bug introduced in https://github.com/elastic/elasticsearch/pull/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. --- docs/changelog/91456.yaml | 5 +++++ .../org/elasticsearch/cluster/metadata/IndexMetadata.java | 7 +++++++ 2 files changed, 12 insertions(+) create mode 100644 docs/changelog/91456.yaml diff --git a/docs/changelog/91456.yaml b/docs/changelog/91456.yaml new file mode 100644 index 0000000000000..609f4ba5691b2 --- /dev/null +++ b/docs/changelog/91456.yaml @@ -0,0 +1,5 @@ +pr: 91456 +summary: Fix corrupted Metadata from index and alias having the same name +area: Cluster Coordination +type: bug +issues: [] diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java index 383800c612e11..428f9d5c1db6c 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java @@ -2024,6 +2024,13 @@ public IndexMetadata build() { } } + var aliasesMap = aliases.build(); + for (AliasMetadata alias : aliasesMap.values()) { + if (alias.alias().equals(index)) { + throw new IllegalArgumentException("alias name [" + index + "] self-conflicts with index name"); + } + } + final boolean isSearchableSnapshot = SearchableSnapshotsSettings.isSearchableSnapshotStore(settings); final String indexMode = settings.get(IndexSettings.MODE.getKey()); final boolean isTsdb = indexMode != null && IndexMode.TIME_SERIES.getName().equals(indexMode.toLowerCase(Locale.ROOT)); From 3274731bd9ff48345abb8a97e6e140403c57ac70 Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Tue, 29 Nov 2022 10:53:29 +0100 Subject: [PATCH 2/2] Implement repair functionality for aliases colliding with indices bug (#91887) Follow up to #91456 implementing an automated fix for indices corrupted in 8.5. --- .../cluster/metadata/IndexMetadata.java | 35 ++++++++++----- .../cluster/metadata/IndexMetadataTests.java | 45 ++++++++++++++----- 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java index 428f9d5c1db6c..4113317d32f60 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java @@ -8,6 +8,8 @@ package org.elasticsearch.cluster.metadata; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.elasticsearch.Version; import org.elasticsearch.action.admin.indices.rollover.RolloverInfo; import org.elasticsearch.action.support.ActiveShardCount; @@ -82,6 +84,8 @@ public class IndexMetadata implements Diffable, ToXContentFragment { + private static final Logger logger = LogManager.getLogger(IndexMetadata.class); + public static final ClusterBlock INDEX_READ_ONLY_BLOCK = new ClusterBlock( 5, "index read-only (api)", @@ -1512,7 +1516,7 @@ public IndexMetadata apply(IndexMetadata part) { builder.rolloverInfos.putAllFromMap(rolloverInfos.apply(part.rolloverInfos)); builder.system(isSystem); builder.timestampRange(timestampRange); - return builder.build(); + return builder.build(true); } } @@ -1573,7 +1577,7 @@ public static IndexMetadata readFrom(StreamInput in, @Nullable Function IndexMetadata.builder("index") - .settings(Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT)) - .numberOfShards(1) - .numberOfReplicas(0) - .putAlias(AliasMetadata.builder("index").build()) - .build() - ); - assertEquals("alias name [index] self-conflicts with index name", iae.getMessage()); + { + final IllegalArgumentException iae = expectThrows( + IllegalArgumentException.class, + () -> IndexMetadata.builder("index") + .settings(Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT)) + .numberOfShards(1) + .numberOfReplicas(0) + .putAlias(AliasMetadata.builder("index").build()) + .build(randomBoolean()) + ); + assertEquals("alias name [index] self-conflicts with index name", iae.getMessage()); + } + { + final IllegalArgumentException iae = expectThrows( + IllegalArgumentException.class, + () -> IndexMetadata.builder("index") + .settings(Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.V_8_5_0)) + .numberOfShards(1) + .numberOfReplicas(0) + .putAlias(AliasMetadata.builder("index").build()) + .build(false) + ); + assertEquals("alias name [index] self-conflicts with index name", iae.getMessage()); + } + } + + public void testRepairIndexAndAliasWithSameName() { + final IndexMetadata indexMetadata = IndexMetadata.builder("index") + .settings(Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.V_8_5_0)) + .numberOfShards(1) + .numberOfReplicas(0) + .putAlias(AliasMetadata.builder("index").build()) + .build(true); + assertThat(indexMetadata.getAliases(), hasKey("index-alias-corrupted-by-8-5")); } private static Settings indexSettingsWithDataTier(String dataTier) {