Skip to content

Remove usages of Metadata.Builder#indexGraveyard #129041

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.metadata.IndexGraveyard;
import org.elasticsearch.cluster.metadata.IndexMetadata;
import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.metadata.ProjectMetadata;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.core.SuppressForbidden;
Expand Down Expand Up @@ -126,9 +126,9 @@ private void submitUnbatchedTask(@SuppressWarnings("SameParameterValue") String
}

private ClusterState deleteDanglingIndex(ClusterState currentState, Index indexToDelete) {
final Metadata metaData = currentState.getMetadata();
final var project = currentState.metadata().getProject();

for (Map.Entry<String, IndexMetadata> each : metaData.getProject().indices().entrySet()) {
for (Map.Entry<String, IndexMetadata> each : project.indices().entrySet()) {
if (indexToDelete.getUUID().equals(each.getValue().getIndexUUID())) {
throw new IllegalArgumentException(
"Refusing to delete dangling index "
Expand All @@ -143,18 +143,13 @@ private ClusterState deleteDanglingIndex(ClusterState currentState, Index indexT
// By definition, a dangling index is an index not present in the cluster state and with no tombstone,
// so we shouldn't reach this point if these conditions aren't met. For super-safety, however, check
// that a tombstone doesn't already exist for this index.
if (metaData.getProject().indexGraveyard().containsIndex(indexToDelete)) {
if (project.indexGraveyard().containsIndex(indexToDelete)) {
return currentState;
}

Metadata.Builder metaDataBuilder = Metadata.builder(metaData);

final IndexGraveyard newGraveyard = IndexGraveyard.builder(metaDataBuilder.indexGraveyard())
.addTombstone(indexToDelete)
.build(settings);
metaDataBuilder.indexGraveyard(newGraveyard);

return ClusterState.builder(currentState).metadata(metaDataBuilder.build()).build();
final IndexGraveyard newGraveyard = IndexGraveyard.builder(project.indexGraveyard()).addTombstone(indexToDelete).build(settings);
final ProjectMetadata updatedProject = ProjectMetadata.builder(project).indexGraveyard(newGraveyard).build();
return ClusterState.builder(currentState).putProjectMetadata(updatedProject).build();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1780,17 +1780,6 @@ public Builder removeReservedState(ReservedStateMetadata metadata) {
return this;
}

@Deprecated(forRemoval = true)
public Builder indexGraveyard(final IndexGraveyard indexGraveyard) {
getSingleProject().indexGraveyard(indexGraveyard);
return this;
}

@Deprecated(forRemoval = true)
public IndexGraveyard indexGraveyard() {
return getSingleProject().indexGraveyard();
}

@Deprecated(forRemoval = true)
public Builder updateSettings(Settings settings, String... indices) {
getSingleProject().updateSettings(settings, indices);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -702,20 +702,24 @@ private static ClusterState nextState(
final ClusterState.Builder builder = ClusterState.builder(previousState);
builder.stateUUID(UUIDs.randomBase64UUID());
final Metadata.Builder metaBuilder = Metadata.builder(previousState.metadata());
// The refactorings required to pass an explicit project ID to this method (and the state creation methods) is not worth it.
final var previousProject = previousState.metadata().projects().values().iterator().next();
final ProjectMetadata.Builder projectBuilder = ProjectMetadata.builder(previousProject);
if (changeClusterUUID || addedIndices.size() > 0 || deletedIndices.size() > 0) {
// there is some change in metadata cluster state
if (changeClusterUUID) {
metaBuilder.clusterUUID(UUIDs.randomBase64UUID());
}
for (Index index : addedIndices) {
metaBuilder.put(createIndexMetadata(index), true);
projectBuilder.put(createIndexMetadata(index), true);
}
for (Index index : deletedIndices) {
metaBuilder.remove(index.getName());
IndexGraveyard.Builder graveyardBuilder = IndexGraveyard.builder(metaBuilder.indexGraveyard());
projectBuilder.remove(index.getName());
IndexGraveyard.Builder graveyardBuilder = IndexGraveyard.builder(projectBuilder.indexGraveyard());
graveyardBuilder.addTombstone(index);
metaBuilder.indexGraveyard(graveyardBuilder.build());
projectBuilder.indexGraveyard(graveyardBuilder.build());
}
metaBuilder.put(projectBuilder);
builder.metadata(metaBuilder);
}
if (numNodesToRemove > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
import org.elasticsearch.cluster.metadata.IndexGraveyard;
import org.elasticsearch.cluster.metadata.IndexMetadata;
import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.metadata.ProjectId;
import org.elasticsearch.cluster.metadata.ProjectMetadata;
import org.elasticsearch.common.UUIDs;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.core.FixForMultiProject;
import org.elasticsearch.index.Index;
import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.test.ESTestCase;
Expand Down Expand Up @@ -93,8 +96,8 @@ private void runLoadStateTest(boolean hasMissingCustoms, boolean preserveUnknown
}

private Metadata randomMeta() {
Metadata.Builder mdBuilder = Metadata.builder();
mdBuilder.generateClusterUuidIfNeeded();
@FixForMultiProject // Pass random project ID when usages are namespaced.
ProjectMetadata.Builder projectBuilder = ProjectMetadata.builder(ProjectId.DEFAULT);
int numDelIndices = randomIntBetween(0, 5);
final IndexGraveyard.Builder graveyard = IndexGraveyard.builder();
for (int i = 0; i < numDelIndices; i++) {
Expand All @@ -105,11 +108,11 @@ private Metadata randomMeta() {
for (int i = 0; i < numDataStreams; i++) {
String dataStreamName = "name" + 1;
IndexMetadata backingIndex = createFirstBackingIndex(dataStreamName).build();
mdBuilder.put(newInstance(dataStreamName, List.of(backingIndex.getIndex())));
projectBuilder.put(newInstance(dataStreamName, List.of(backingIndex.getIndex())));
}
}
mdBuilder.indexGraveyard(graveyard.build());
return mdBuilder.build();
projectBuilder.indexGraveyard(graveyard.build());
return Metadata.builder().generateClusterUuidIfNeeded().put(projectBuilder).build();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.common.xcontent.ChunkedToXContent;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.core.FixForMultiProject;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.core.Predicates;
import org.elasticsearch.core.SuppressForbidden;
Expand Down Expand Up @@ -607,27 +608,35 @@ public void testUnknownFieldIndexMetadata() throws IOException {
}

public void testMetadataGlobalStateChangesOnIndexDeletions() {
final var projectId = randomProjectIdOrDefault();
IndexGraveyard.Builder builder = IndexGraveyard.builder();
builder.addTombstone(new Index("idx1", UUIDs.randomBase64UUID()));
final Metadata metadata1 = Metadata.builder().indexGraveyard(builder.build()).build();
builder = IndexGraveyard.builder(metadata1.getProject().indexGraveyard());
final Metadata metadata1 = Metadata.builder().put(ProjectMetadata.builder(projectId).indexGraveyard(builder.build())).build();
builder = IndexGraveyard.builder(metadata1.getProject(projectId).indexGraveyard());
builder.addTombstone(new Index("idx2", UUIDs.randomBase64UUID()));
final Metadata metadata2 = Metadata.builder(metadata1).indexGraveyard(builder.build()).build();
final Metadata metadata2 = Metadata.builder(metadata1)
.put(ProjectMetadata.builder(metadata1.getProject(projectId)).indexGraveyard(builder.build()))
.build();
assertFalse("metadata not equal after adding index deletions", Metadata.isGlobalStateEquals(metadata1, metadata2));
final Metadata metadata3 = Metadata.builder(metadata2).build();
assertTrue("metadata equal when not adding index deletions", Metadata.isGlobalStateEquals(metadata2, metadata3));
}

public void testXContentWithIndexGraveyard() throws IOException {
@FixForMultiProject // XContent serialization and parsing with a random project ID currently only works when serializing in MP mode
final var projectId = ProjectId.DEFAULT;
final IndexGraveyard graveyard = IndexGraveyardTests.createRandom();
final Metadata originalMeta = Metadata.builder().indexGraveyard(graveyard).build();
final Metadata originalMeta = Metadata.builder().put(ProjectMetadata.builder(projectId).indexGraveyard(graveyard)).build();
final XContentBuilder builder = JsonXContent.contentBuilder();
builder.startObject();
Metadata.FORMAT.toXContent(builder, originalMeta);
builder.endObject();
try (XContentParser parser = createParser(JsonXContent.jsonXContent, BytesReference.bytes(builder))) {
final Metadata fromXContentMeta = Metadata.fromXContent(parser);
assertThat(fromXContentMeta.getProject().indexGraveyard(), equalTo(originalMeta.getProject().indexGraveyard()));
assertThat(
fromXContentMeta.getProject(projectId).indexGraveyard(),
equalTo(originalMeta.getProject(projectId).indexGraveyard())
);
}
}

Expand Down Expand Up @@ -975,15 +984,16 @@ public void testGlobalStateEqualsCoordinationMetadata() {
}

public void testSerializationWithIndexGraveyard() throws IOException {
final var projectId = randomProjectIdOrDefault();
final IndexGraveyard graveyard = IndexGraveyardTests.createRandom();
final Metadata originalMeta = Metadata.builder().indexGraveyard(graveyard).build();
final Metadata originalMeta = Metadata.builder().put(ProjectMetadata.builder(projectId).indexGraveyard(graveyard)).build();
final BytesStreamOutput out = new BytesStreamOutput();
originalMeta.writeTo(out);
NamedWriteableRegistry namedWriteableRegistry = new NamedWriteableRegistry(ClusterModule.getNamedWriteables());
final Metadata fromStreamMeta = Metadata.readFrom(
new NamedWriteableAwareStreamInput(out.bytes().streamInput(), namedWriteableRegistry)
);
assertThat(fromStreamMeta.getProject().indexGraveyard(), equalTo(fromStreamMeta.getProject().indexGraveyard()));
assertThat(fromStreamMeta.getProject(projectId).indexGraveyard(), equalTo(originalMeta.getProject(projectId).indexGraveyard()));
}

public void testFindMappings() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
import org.elasticsearch.cluster.metadata.IndexGraveyard;
import org.elasticsearch.cluster.metadata.IndexMetadata;
import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.metadata.ProjectId;
import org.elasticsearch.cluster.metadata.ProjectMetadata;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.core.FixForMultiProject;
import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexVersion;
Expand Down Expand Up @@ -85,7 +88,8 @@ public void testDanglingIndicesNotReportedWhenTombstonePresent() throws Exceptio
MetaStateWriterUtils.writeIndex(env, "test_write", dangledIndex);

final IndexGraveyard graveyard = IndexGraveyard.builder().addTombstone(dangledIndex.getIndex()).build();
final Metadata metadata = Metadata.builder().indexGraveyard(graveyard).build();
@FixForMultiProject // Use random project ID
final Metadata metadata = Metadata.builder().put(ProjectMetadata.builder(ProjectId.DEFAULT).indexGraveyard(graveyard)).build();

DanglingIndicesState danglingState = createDanglingIndicesState(metaStateService, metadata);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.EsExecutors;
import org.elasticsearch.core.FixForMultiProject;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.env.ShardLockObtainFailedException;
Expand Down Expand Up @@ -546,8 +547,9 @@ public void testIndexAndTombstoneWithSameNameOnStartup() throws Exception {
.build();
final Index tombstonedIndex = new Index(indexName, UUIDs.randomBase64UUID());
final IndexGraveyard graveyard = IndexGraveyard.builder().addTombstone(tombstonedIndex).build();
final Metadata metadata = Metadata.builder().put(indexMetadata, true).indexGraveyard(graveyard).build();
final ClusterState clusterState = new ClusterState.Builder(new ClusterName("testCluster")).metadata(metadata).build();
@FixForMultiProject // Use random project-id
final var project = ProjectMetadata.builder(ProjectId.DEFAULT).put(indexMetadata, true).indexGraveyard(graveyard).build();
final ClusterState clusterState = new ClusterState.Builder(new ClusterName("testCluster")).putProjectMetadata(project).build();
// if all goes well, this won't throw an exception, otherwise, it will throw an IllegalStateException
indicesService.verifyIndexIsDeleted(tombstonedIndex, clusterState);
}
Expand Down