From 9f7f18140421406e764ed6e2b0470b51d4a90ffe Mon Sep 17 00:00:00 2001 From: Niels Bauman Date: Tue, 8 Jul 2025 17:39:10 -0300 Subject: [PATCH] Make template substitution in bulk simulation API project-aware Resolve the correct project instead of using the deprecated method. --- .../bulk/TransportSimulateBulkActionIT.java | 7 ++++-- .../bulk/TransportAbstractBulkAction.java | 22 ++++++++----------- .../TransportSimulateBulkActionTests.java | 13 ++++++----- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/server/src/internalClusterTest/java/org/elasticsearch/action/bulk/TransportSimulateBulkActionIT.java b/server/src/internalClusterTest/java/org/elasticsearch/action/bulk/TransportSimulateBulkActionIT.java index 4c1324cb0378a..cabe428a7487c 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/action/bulk/TransportSimulateBulkActionIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/action/bulk/TransportSimulateBulkActionIT.java @@ -24,6 +24,7 @@ import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; +import org.elasticsearch.cluster.metadata.ProjectId; import org.elasticsearch.cluster.metadata.Template; import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.settings.Settings; @@ -85,7 +86,8 @@ public void testMappingValidationIndexExists() { assertThat(searchResponse.getHits().getTotalHits().value(), equalTo(0L)); searchResponse.decRef(); ClusterStateResponse clusterStateResponse = admin().cluster().state(new ClusterStateRequest(TEST_REQUEST_TIMEOUT)).actionGet(); - Map indexMapping = clusterStateResponse.getState().metadata().getProject().index(indexName).mapping().sourceAsMap(); + final var project = clusterStateResponse.getState().metadata().getProject(ProjectId.DEFAULT); + Map indexMapping = project.index(indexName).mapping().sourceAsMap(); Map fields = (Map) indexMapping.get("properties"); assertThat(fields.size(), equalTo(1)); } @@ -142,7 +144,8 @@ public void testMappingValidationIndexExistsTemplateSubstitutions() throws IOExc assertThat(searchResponse.getHits().getTotalHits().value(), equalTo(0L)); searchResponse.decRef(); ClusterStateResponse clusterStateResponse = admin().cluster().state(new ClusterStateRequest(TEST_REQUEST_TIMEOUT)).actionGet(); - Map indexMapping = clusterStateResponse.getState().metadata().getProject().index(indexName).mapping().sourceAsMap(); + final var project = clusterStateResponse.getState().metadata().getProject(ProjectId.DEFAULT); + Map indexMapping = project.index(indexName).mapping().sourceAsMap(); Map fields = (Map) indexMapping.get("properties"); assertThat(fields.size(), equalTo(1)); } diff --git a/server/src/main/java/org/elasticsearch/action/bulk/TransportAbstractBulkAction.java b/server/src/main/java/org/elasticsearch/action/bulk/TransportAbstractBulkAction.java index 96fbb2c5d6649..f003cd3fc107d 100644 --- a/server/src/main/java/org/elasticsearch/action/bulk/TransportAbstractBulkAction.java +++ b/server/src/main/java/org/elasticsearch/action/bulk/TransportAbstractBulkAction.java @@ -26,7 +26,6 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.metadata.ProjectId; import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.project.ProjectResolver; @@ -34,7 +33,6 @@ import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.core.Assertions; -import org.elasticsearch.core.FixForMultiProject; import org.elasticsearch.core.Releasable; import org.elasticsearch.core.TimeValue; import org.elasticsearch.index.IndexingPressure; @@ -193,34 +191,33 @@ private boolean applyPipelines(Task task, BulkRequest bulkRequest, Executor exec boolean hasIndexRequestsWithPipelines = false; ClusterState state = clusterService.state(); ProjectId projectId = projectResolver.getProjectId(); - final Metadata metadata; + final ProjectMetadata project; Map componentTemplateSubstitutions = bulkRequest.getComponentTemplateSubstitutions(); Map indexTemplateSubstitutions = bulkRequest.getIndexTemplateSubstitutions(); if (bulkRequest.isSimulated() && (componentTemplateSubstitutions.isEmpty() == false || indexTemplateSubstitutions.isEmpty() == false)) { /* - * If this is a simulated request, and there are template substitutions, then we want to create and use a new metadata that has + * If this is a simulated request, and there are template substitutions, then we want to create and use a new project that has * those templates. That is, we want to add the new templates (which will replace any that already existed with the same name), * and remove the indices and data streams that are referred to from the bulkRequest so that we get settings from the templates * rather than from the indices/data streams. */ - Metadata originalMetadata = state.metadata(); - @FixForMultiProject // properly ensure simulated actions work with MP - Metadata.Builder simulatedMetadataBuilder = Metadata.builder(originalMetadata); + ProjectMetadata originalProject = state.metadata().getProject(projectId); + ProjectMetadata.Builder simulatedMetadataBuilder = ProjectMetadata.builder(originalProject); if (componentTemplateSubstitutions.isEmpty() == false) { Map updatedComponentTemplates = new HashMap<>(); - updatedComponentTemplates.putAll(originalMetadata.getProject(projectId).componentTemplates()); + updatedComponentTemplates.putAll(originalProject.componentTemplates()); updatedComponentTemplates.putAll(componentTemplateSubstitutions); simulatedMetadataBuilder.componentTemplates(updatedComponentTemplates); } if (indexTemplateSubstitutions.isEmpty() == false) { Map updatedIndexTemplates = new HashMap<>(); - updatedIndexTemplates.putAll(originalMetadata.getProject(projectId).templatesV2()); + updatedIndexTemplates.putAll(originalProject.templatesV2()); updatedIndexTemplates.putAll(indexTemplateSubstitutions); simulatedMetadataBuilder.indexTemplates(updatedIndexTemplates); } /* - * We now remove the index from the simulated metadata to force the templates to be used. Note that simulated requests are + * We now remove the index from the simulated project to force the templates to be used. Note that simulated requests are * always index requests -- no other type of request is supported. */ for (DocWriteRequest actionRequest : bulkRequest.requests) { @@ -236,12 +233,11 @@ private boolean applyPipelines(Task task, BulkRequest bulkRequest, Executor exec } } } - metadata = simulatedMetadataBuilder.build(); + project = simulatedMetadataBuilder.build(); } else { - metadata = state.getMetadata(); + project = state.metadata().getProject(projectId); } - ProjectMetadata project = metadata.getProject(projectId); Map resolvedPipelineCache = new HashMap<>(); for (DocWriteRequest actionRequest : bulkRequest.requests) { IndexRequest indexRequest = getIndexWriteRequest(actionRequest); diff --git a/server/src/test/java/org/elasticsearch/action/bulk/TransportSimulateBulkActionTests.java b/server/src/test/java/org/elasticsearch/action/bulk/TransportSimulateBulkActionTests.java index c422efed0f254..eab44f1c56b16 100644 --- a/server/src/test/java/org/elasticsearch/action/bulk/TransportSimulateBulkActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/bulk/TransportSimulateBulkActionTests.java @@ -19,7 +19,8 @@ import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.metadata.IndexTemplateMetadata; -import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.metadata.ProjectId; +import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.project.TestProjectResolvers; @@ -229,7 +230,7 @@ public void testIndexDataWithValidation() throws IOException { Map indicesMap = new HashMap<>(); Map v1Templates = new HashMap<>(); Map v2Templates = new HashMap<>(); - Metadata.Builder metadataBuilder = new Metadata.Builder(); + ProjectMetadata.Builder projectBuilder = ProjectMetadata.builder(ProjectId.DEFAULT); Set indicesWithInvalidMappings = new HashSet<>(); for (int i = 0; i < bulkItemCount; i++) { Map source = Map.of(randomAlphaOfLength(10), randomAlphaOfLength(5)); @@ -275,10 +276,10 @@ public void testIndexDataWithValidation() throws IOException { default -> throw new AssertionError("Illegal branch"); } } - metadataBuilder.indices(indicesMap); - metadataBuilder.templates(v1Templates); - metadataBuilder.indexTemplates(v2Templates); - ClusterServiceUtils.setState(clusterService, new ClusterState.Builder(clusterService.state()).metadata(metadataBuilder)); + projectBuilder.indices(indicesMap); + projectBuilder.templates(v1Templates); + projectBuilder.indexTemplates(v2Templates); + ClusterServiceUtils.setState(clusterService, ClusterState.builder(clusterService.state()).putProjectMetadata(projectBuilder)); AtomicBoolean onResponseCalled = new AtomicBoolean(false); ActionListener listener = new ActionListener<>() { @Override