Skip to content

Commit

Permalink
Implement repair functionality for aliases colliding with indices bug (
Browse files Browse the repository at this point in the history
…elastic#91887)

Follow up to elastic#91456 implementing an automated fix for indices corrupted in 8.5.
  • Loading branch information
original-brownbear committed Nov 29, 2022
1 parent e75a665 commit d77b163
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -83,6 +85,8 @@

public class IndexMetadata implements Diffable<IndexMetadata>, 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)",
Expand Down Expand Up @@ -1589,7 +1593,7 @@ public IndexMetadata apply(IndexMetadata part) {
builder.stats(stats);
builder.indexWriteLoadForecast(indexWriteLoadForecast);
builder.shardSizeInBytesForecast(shardSizeInBytesForecast);
return builder.build();
return builder.build(true);
}
}

Expand Down Expand Up @@ -1656,7 +1660,7 @@ public static IndexMetadata readFrom(StreamInput in, @Nullable Function<String,
builder.indexWriteLoadForecast(in.readOptionalDouble());
builder.shardSizeInBytesForecast(in.readOptionalLong());
}
return builder.build();
return builder.build(true);
}

/**
Expand Down Expand Up @@ -2012,6 +2016,11 @@ public Builder shardSizeInBytesForecast(Long shardSizeInBytesForecast) {
}

public IndexMetadata build() {
return build(false);
}

// package private for testing
IndexMetadata build(boolean repair) {
/*
* We expect that the metadata has been properly built to set the number of shards and the number of replicas, and do not rely
* on the default values here. Those must have been set upstream.
Expand Down Expand Up @@ -2140,7 +2149,16 @@ 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");
if (repair && indexCreatedVersion.equals(Version.V_8_5_0)) {
var updatedBuilder = ImmutableOpenMap.builder(aliasesMap);
final var brokenAlias = updatedBuilder.remove(index);
final var fixedAlias = AliasMetadata.newAliasMetadata(brokenAlias, index + "-alias-corrupted-by-8-5");
aliasesMap = updatedBuilder.fPut(fixedAlias.getAlias(), fixedAlias).build();
logger.warn("Repaired corrupted alias with the same name as its index for [{}]", index);
break;
} else {
throw new IllegalArgumentException("alias name [" + index + "] self-conflicts with index name");
}
}
}

Expand Down Expand Up @@ -2463,7 +2481,7 @@ public static IndexMetadata fromXContent(XContentParser parser, Map<String, Mapp
assert settingsVersion : "settings version should be present for indices created on or after 6.5.0";
assert indexCreatedVersion(builder.settings).before(Version.V_7_2_0) || aliasesVersion
: "aliases version should be present for indices created on or after 7.2.0";
return builder.build();
return builder.build(true);
}

/**
Expand Down Expand Up @@ -2574,7 +2592,7 @@ public static IndexMetadata legacyFromXContent(XContentParser parser) throws IOE
builder.putMapping(MappingMetadata.EMPTY_MAPPINGS); // just make sure it's not empty so that _source can be read
}

IndexMetadata indexMetadata = builder.build();
IndexMetadata indexMetadata = builder.build(true);
assert indexMetadata.getCreationVersion().isLegacyIndexVersion();
assert indexMetadata.getCompatibilityVersion().isLegacyIndexVersion();
return indexMetadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import static org.elasticsearch.cluster.metadata.IndexMetadata.parseIndexNameCounter;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;

public class IndexMetadataTests extends ESTestCase {
Expand Down Expand Up @@ -497,16 +498,40 @@ public void testLifeCyclePolicyName() {
}

public void testIndexAndAliasWithSameName() {
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()
);
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) {
Expand Down

0 comments on commit d77b163

Please sign in to comment.