From 886afe55bdb033af1453c1eaf701fa1de4bb2a34 Mon Sep 17 00:00:00 2001 From: Pooya Salehi Date: Mon, 16 Jun 2025 11:39:00 +0200 Subject: [PATCH 1/3] integrate project global blocks into existing trasnport actions --- .../TransportCreateDataStreamAction.java | 2 +- .../TransportDeleteDataStreamAction.java | 2 +- ...TransportGetDataStreamLifecycleAction.java | 2 +- .../TransportDeleteStoredScriptAction.java | 8 +++-- .../forcemerge/TransportForceMergeAction.java | 2 +- .../TransportAddIndexBlockAction.java | 4 +-- .../put/TransportUpdateSettingsAction.java | 3 +- ...ransportDeleteComponentTemplateAction.java | 2 +- ...rtDeleteComposableIndexTemplateAction.java | 2 +- .../TransportDeleteIndexTemplateAction.java | 2 +- .../TransportGetComponentTemplateAction.java | 5 +-- ...sportGetComposableIndexTemplateAction.java | 2 +- .../query/TransportValidateQueryAction.java | 2 +- .../action/bulk/BulkOperation.java | 3 +- .../bulk/TransportAbstractBulkAction.java | 5 +-- .../TransportFieldCapabilitiesAction.java | 5 +-- .../action/get/TransportMultiGetAction.java | 2 +- .../ingest/DeletePipelineTransportAction.java | 2 +- .../ingest/GetPipelineTransportAction.java | 6 +++- .../ingest/PutPipelineTransportAction.java | 2 +- .../search/TransportMultiSearchAction.java | 12 +++++-- .../action/search/TransportSearchAction.java | 9 ++--- .../TransportMultiTermVectorsAction.java | 2 +- .../cluster/block/ClusterBlocks.java | 36 +++++++++++++++++++ .../UpdatePersistentTaskStatusAction.java | 2 +- .../search/MultiSearchActionTookTests.java | 7 ++-- .../TransportMultiSearchActionTests.java | 7 ++-- .../TransportDeleteEnrichPolicyAction.java | 2 +- .../TransportExecuteEnrichPolicyAction.java | 8 +++-- ...nsportDeleteAnalyticsCollectionAction.java | 8 +++-- ...ransportDeleteInferenceEndpointAction.java | 8 +++-- ...ortDeleteInferenceEndpointActionTests.java | 4 ++- ...ansportDeleteDataFrameAnalyticsAction.java | 8 +++-- .../action/TransportDeleteDatafeedAction.java | 8 +++-- .../ml/action/TransportDeleteJobAction.java | 8 +++-- .../TransportDeleteTrainedModelAction.java | 8 +++-- ...ransportDeleteTrainedModelAliasAction.java | 8 +++-- .../action/TransportMonitoringBulkAction.java | 2 ++ .../exporter/local/LocalExporter.java | 4 +++ .../TransportDeleteTransformAction.java | 8 +++-- 40 files changed, 164 insertions(+), 58 deletions(-) diff --git a/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportCreateDataStreamAction.java b/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportCreateDataStreamAction.java index 2c8212ab5e36d..114715bdab76e 100644 --- a/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportCreateDataStreamAction.java +++ b/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportCreateDataStreamAction.java @@ -83,6 +83,6 @@ protected void masterOperation( @Override protected ClusterBlockException checkBlock(CreateDataStreamAction.Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } } diff --git a/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportDeleteDataStreamAction.java b/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportDeleteDataStreamAction.java index 1df182b33649c..b3ba8286acced 100644 --- a/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportDeleteDataStreamAction.java +++ b/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportDeleteDataStreamAction.java @@ -161,6 +161,6 @@ static ClusterState removeDataStream( @Override protected ClusterBlockException checkBlock(DeleteDataStreamAction.Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } } diff --git a/modules/data-streams/src/main/java/org/elasticsearch/datastreams/lifecycle/action/TransportGetDataStreamLifecycleAction.java b/modules/data-streams/src/main/java/org/elasticsearch/datastreams/lifecycle/action/TransportGetDataStreamLifecycleAction.java index e564ddf8dddae..48c54ab67b562 100644 --- a/modules/data-streams/src/main/java/org/elasticsearch/datastreams/lifecycle/action/TransportGetDataStreamLifecycleAction.java +++ b/modules/data-streams/src/main/java/org/elasticsearch/datastreams/lifecycle/action/TransportGetDataStreamLifecycleAction.java @@ -122,6 +122,6 @@ protected void localClusterStateOperation( @Override protected ClusterBlockException checkBlock(GetDataStreamLifecycleAction.Request request, ProjectState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ); + return state.blocks().globalBlockedException(state.projectId(), ClusterBlockLevel.METADATA_READ); } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportDeleteStoredScriptAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportDeleteStoredScriptAction.java index 41c0e8aaedc83..4a5339484a54d 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportDeleteStoredScriptAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportDeleteStoredScriptAction.java @@ -17,6 +17,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.injection.guice.Inject; @@ -28,13 +29,15 @@ public class TransportDeleteStoredScriptAction extends AcknowledgedTransportMasterNodeAction { public static final ActionType TYPE = new ActionType<>("cluster:admin/script/delete"); + private final ProjectResolver projectResolver; @Inject public TransportDeleteStoredScriptAction( TransportService transportService, ClusterService clusterService, ThreadPool threadPool, - ActionFilters actionFilters + ActionFilters actionFilters, + ProjectResolver projectResolver ) { super( TYPE.name(), @@ -45,6 +48,7 @@ public TransportDeleteStoredScriptAction( DeleteStoredScriptRequest::new, EsExecutors.DIRECT_EXECUTOR_SERVICE ); + this.projectResolver = projectResolver; } @Override @@ -59,7 +63,7 @@ protected void masterOperation( @Override protected ClusterBlockException checkBlock(DeleteStoredScriptRequest request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/forcemerge/TransportForceMergeAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/forcemerge/TransportForceMergeAction.java index 178ed0eb05ca3..8f6df9a1c3a61 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/forcemerge/TransportForceMergeAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/forcemerge/TransportForceMergeAction.java @@ -119,7 +119,7 @@ protected ShardsIterator shards(ClusterState clusterState, ForceMergeRequest req @Override protected ClusterBlockException checkGlobalBlock(ClusterState state, ForceMergeRequest request) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/readonly/TransportAddIndexBlockAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/readonly/TransportAddIndexBlockAction.java index 4a8d6041c9756..e51edfa0844a7 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/readonly/TransportAddIndexBlockAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/readonly/TransportAddIndexBlockAction.java @@ -87,11 +87,11 @@ protected void doExecute(Task task, AddIndexBlockRequest request, ActionListener @Override protected ClusterBlockException checkBlock(AddIndexBlockRequest request, ClusterState state) { + final ProjectMetadata projectMetadata = projectResolver.getProjectMetadata(state); if (request.getBlock().getBlock().levels().contains(ClusterBlockLevel.METADATA_WRITE) - && state.blocks().global(ClusterBlockLevel.METADATA_WRITE).isEmpty()) { + && state.blocks().global(projectMetadata.id(), ClusterBlockLevel.METADATA_WRITE).isEmpty()) { return null; } - final ProjectMetadata projectMetadata = projectResolver.getProjectMetadata(state); return state.blocks() .indicesBlockedException( projectMetadata.id(), diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/TransportUpdateSettingsAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/TransportUpdateSettingsAction.java index a8e53318896b8..0276d1a238166 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/TransportUpdateSettingsAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/settings/put/TransportUpdateSettingsAction.java @@ -85,7 +85,8 @@ public TransportUpdateSettingsAction( @Override protected ClusterBlockException checkBlock(UpdateSettingsRequest request, ClusterState state) { // allow for dedicated changes to the metadata blocks, so we don't block those to allow to "re-enable" it - ClusterBlockException globalBlock = state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + ClusterBlockException globalBlock = state.blocks() + .globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); if (globalBlock != null) { return globalBlock; } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteComponentTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteComponentTemplateAction.java index feaa7cc32b11c..11ca49c6398b9 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteComponentTemplateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteComponentTemplateAction.java @@ -65,7 +65,7 @@ public TransportDeleteComponentTemplateAction( @Override protected ClusterBlockException checkBlock(Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteComposableIndexTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteComposableIndexTemplateAction.java index f0ca3b05c61c3..a91a3c2217e88 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteComposableIndexTemplateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteComposableIndexTemplateAction.java @@ -64,7 +64,7 @@ public TransportDeleteComposableIndexTemplateAction( @Override protected ClusterBlockException checkBlock(Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java index 866a7ddd9fb47..4641fb829615c 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java @@ -62,7 +62,7 @@ public TransportDeleteIndexTemplateAction( @Override protected ClusterBlockException checkBlock(DeleteIndexTemplateRequest request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComponentTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComponentTemplateAction.java index b2148a0053aaf..5ca4a1ebd618a 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComponentTemplateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComponentTemplateAction.java @@ -38,6 +38,7 @@ public class TransportGetComponentTemplateAction extends TransportLocalProjectMe GetComponentTemplateAction.Response> { private final ClusterSettings clusterSettings; + private final ProjectResolver projectResolver; /** * NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC it must be registered with the TransportService until @@ -61,7 +62,7 @@ public TransportGetComponentTemplateAction( projectResolver ); clusterSettings = clusterService.getClusterSettings(); - + this.projectResolver = projectResolver; transportService.registerRequestHandler( actionName, executor, @@ -74,7 +75,7 @@ public TransportGetComponentTemplateAction( @Override protected ClusterBlockException checkBlock(GetComponentTemplateAction.Request request, ProjectState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_READ); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComposableIndexTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComposableIndexTemplateAction.java index 25bd81baa900f..7139bc269174d 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComposableIndexTemplateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComposableIndexTemplateAction.java @@ -74,7 +74,7 @@ public TransportGetComposableIndexTemplateAction( @Override protected ClusterBlockException checkBlock(GetComposableIndexTemplateAction.Request request, ProjectState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ); + return state.blocks().globalBlockedException(state.projectId(), ClusterBlockLevel.METADATA_READ); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/validate/query/TransportValidateQueryAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/validate/query/TransportValidateQueryAction.java index 75e4f4ce4b50d..1d9ba297c35c6 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/validate/query/TransportValidateQueryAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/validate/query/TransportValidateQueryAction.java @@ -176,7 +176,7 @@ protected List shards(ClusterState clusterState, ValidateQueryReq @Override protected ClusterBlockException checkGlobalBlock(ClusterState state, ValidateQueryRequest request) { - return state.blocks().globalBlockedException(ClusterBlockLevel.READ); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.READ); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/bulk/BulkOperation.java b/server/src/main/java/org/elasticsearch/action/bulk/BulkOperation.java index 83ae6dd538be4..9c5f40577b32c 100644 --- a/server/src/main/java/org/elasticsearch/action/bulk/BulkOperation.java +++ b/server/src/main/java/org/elasticsearch/action/bulk/BulkOperation.java @@ -687,7 +687,8 @@ private void maybeMarkFailureStoreForRollover(DataStream dataStream) { * @return {@code true} if the cluster is currently blocked at all, {@code false} if the cluster has no blocks. */ private boolean handleBlockExceptions(ClusterState state, Runnable retryOperation, Consumer onClusterBlocked) { - ClusterBlockException blockException = state.blocks().globalBlockedException(ClusterBlockLevel.WRITE); + ClusterBlockException blockException = state.blocks() + .globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.WRITE); if (blockException != null) { if (blockException.retryable()) { logger.trace("cluster is blocked, scheduling a retry", blockException); 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 9c8ca93a7744c..d96feb83a218b 100644 --- a/server/src/main/java/org/elasticsearch/action/bulk/TransportAbstractBulkAction.java +++ b/server/src/main/java/org/elasticsearch/action/bulk/TransportAbstractBulkAction.java @@ -142,7 +142,8 @@ private void ensureClusterStateThenForkAndExecute( ActionListener releasingListener ) { final ClusterState initialState = clusterService.state(); - final ClusterBlockException blockException = initialState.blocks().globalBlockedException(ClusterBlockLevel.WRITE); + ProjectId projectId = projectResolver.getProjectId(); + final ClusterBlockException blockException = initialState.blocks().globalBlockedException(projectId, ClusterBlockLevel.WRITE); if (blockException != null) { if (false == blockException.retryable()) { releasingListener.onFailure(blockException); @@ -171,7 +172,7 @@ public void onClusterServiceClose() { public void onTimeout(TimeValue timeout) { releasingListener.onFailure(blockException); } - }, newState -> false == newState.blocks().hasGlobalBlockWithLevel(ClusterBlockLevel.WRITE)); + }, newState -> false == newState.blocks().hasGlobalBlockWithLevel(projectId, ClusterBlockLevel.WRITE)); } else { forkAndExecute(task, bulkRequest, executor, releasingListener); } diff --git a/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java index d64da10e0b2f7..eb45276ce2da0 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java @@ -348,11 +348,12 @@ void executeRemoteRequest( private static void checkIndexBlocks(ProjectState projectState, String[] concreteIndices) { var blocks = projectState.blocks(); - if (blocks.global().isEmpty() && blocks.indices(projectState.projectId()).isEmpty()) { + var projectId = projectState.projectId(); + if (blocks.global(projectId).isEmpty() && blocks.indices(projectId).isEmpty()) { // short circuit optimization because block check below is relatively expensive for many indices return; } - blocks.globalBlockedRaiseException(ClusterBlockLevel.READ); + blocks.globalBlockedRaiseException(projectId, ClusterBlockLevel.READ); for (String index : concreteIndices) { blocks.indexBlockedRaiseException(projectState.projectId(), ClusterBlockLevel.READ, index); } diff --git a/server/src/main/java/org/elasticsearch/action/get/TransportMultiGetAction.java b/server/src/main/java/org/elasticsearch/action/get/TransportMultiGetAction.java index 97b37e1953871..4d85eb840c973 100644 --- a/server/src/main/java/org/elasticsearch/action/get/TransportMultiGetAction.java +++ b/server/src/main/java/org/elasticsearch/action/get/TransportMultiGetAction.java @@ -68,7 +68,7 @@ public TransportMultiGetAction( protected void doExecute(Task task, final MultiGetRequest request, final ActionListener listener) { ClusterState clusterState = clusterService.state(); ProjectMetadata project = projectResolver.getProjectMetadata(clusterState); - clusterState.blocks().globalBlockedRaiseException(ClusterBlockLevel.READ); + clusterState.blocks().globalBlockedRaiseException(project.id(), ClusterBlockLevel.READ); final AtomicArray responses = new AtomicArray<>(request.items.size()); final Map shardRequests = new HashMap<>(); diff --git a/server/src/main/java/org/elasticsearch/action/ingest/DeletePipelineTransportAction.java b/server/src/main/java/org/elasticsearch/action/ingest/DeletePipelineTransportAction.java index 8f9c6d3848df4..644239d127450 100644 --- a/server/src/main/java/org/elasticsearch/action/ingest/DeletePipelineTransportAction.java +++ b/server/src/main/java/org/elasticsearch/action/ingest/DeletePipelineTransportAction.java @@ -67,7 +67,7 @@ protected void masterOperation( @Override protected ClusterBlockException checkBlock(DeletePipelineRequest request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java b/server/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java index cf0367aa5d4fb..6608cb3d9bb52 100644 --- a/server/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java +++ b/server/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java @@ -27,6 +27,8 @@ public class GetPipelineTransportAction extends TransportLocalProjectMetadataAction { + private final ProjectResolver projectResolver; + /** * NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC it must be registered with the TransportService until * we no longer need to support calling this action remotely. @@ -49,6 +51,8 @@ public GetPipelineTransportAction( projectResolver ); + this.projectResolver = projectResolver; + transportService.registerRequestHandler( actionName, executor, @@ -71,7 +75,7 @@ protected void localClusterStateOperation( @Override protected ClusterBlockException checkBlock(GetPipelineRequest request, ProjectState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_READ); } } diff --git a/server/src/main/java/org/elasticsearch/action/ingest/PutPipelineTransportAction.java b/server/src/main/java/org/elasticsearch/action/ingest/PutPipelineTransportAction.java index 091b95eef12f8..e6c1b00ccb815 100644 --- a/server/src/main/java/org/elasticsearch/action/ingest/PutPipelineTransportAction.java +++ b/server/src/main/java/org/elasticsearch/action/ingest/PutPipelineTransportAction.java @@ -78,7 +78,7 @@ protected void masterOperation(Task task, PutPipelineRequest request, ClusterSta @Override protected ClusterBlockException checkBlock(PutPipelineRequest request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/search/TransportMultiSearchAction.java b/server/src/main/java/org/elasticsearch/action/search/TransportMultiSearchAction.java index 7f10ddc7998ce..dbb010cf92a4f 100644 --- a/server/src/main/java/org/elasticsearch/action/search/TransportMultiSearchAction.java +++ b/server/src/main/java/org/elasticsearch/action/search/TransportMultiSearchAction.java @@ -20,6 +20,7 @@ import org.elasticsearch.client.internal.node.NodeClient; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.AtomicArray; @@ -44,6 +45,7 @@ public class TransportMultiSearchAction extends HandledTransportAction buildPerIndexOriginalIndices( ) { Map res = Maps.newMapWithExpectedSize(indices.length); var blocks = projectState.blocks(); + var projectId = projectState.projectId(); // optimization: mostly we do not have any blocks so there's no point in the expensive per-index checking - boolean hasBlocks = blocks.global().isEmpty() == false || blocks.indices(projectState.projectId()).isEmpty() == false; + boolean hasBlocks = blocks.global(projectId).isEmpty() == false || blocks.indices(projectState.projectId()).isEmpty() == false; // Get a distinct set of index abstraction names present from the resolved expressions to help with the reverse resolution from // concrete index to the expression that produced it. Set indicesAndAliasesResources = indicesAndAliases.stream().map(ResolvedExpression::resource).collect(Collectors.toSet()); for (String index : indices) { if (hasBlocks) { - blocks.indexBlockedRaiseException(projectState.projectId(), ClusterBlockLevel.READ, index); + blocks.indexBlockedRaiseException(projectId, ClusterBlockLevel.READ, index); } String[] aliases = indexNameExpressionResolver.allIndexAliases(projectState.metadata(), index, indicesAndAliases); @@ -346,7 +347,7 @@ void executeRequest( ); final ClusterState clusterState = clusterService.state(); - clusterState.blocks().globalBlockedRaiseException(ClusterBlockLevel.READ); + clusterState.blocks().globalBlockedRaiseException(projectResolver.getProjectId(), ClusterBlockLevel.READ); ProjectState projectState = projectResolver.getProjectState(clusterState); final ResolvedIndices resolvedIndices; @@ -1410,7 +1411,7 @@ static boolean shouldPreFilterSearchShards( private static boolean hasReadOnlyIndices(String[] indices, ProjectState projectState) { var blocks = projectState.blocks(); - if (blocks.global().isEmpty() && blocks.indices(projectState.projectId()).isEmpty()) { + if (blocks.global(projectState.projectId()).isEmpty() && blocks.indices(projectState.projectId()).isEmpty()) { // short circuit optimization because block check below is relatively expensive for many indices return false; } diff --git a/server/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java b/server/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java index 8af9f5db68f98..d16cb518eb2d4 100644 --- a/server/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java +++ b/server/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java @@ -65,7 +65,7 @@ public TransportMultiTermVectorsAction( protected void doExecute(Task task, final MultiTermVectorsRequest request, final ActionListener listener) { ClusterState clusterState = clusterService.state(); ProjectMetadata project = projectResolver.getProjectMetadata(clusterState); - clusterState.blocks().globalBlockedRaiseException(ClusterBlockLevel.READ); + clusterState.blocks().globalBlockedRaiseException(project.id(), ClusterBlockLevel.READ); final AtomicArray responses = new AtomicArray<>(request.requests.size()); diff --git a/server/src/main/java/org/elasticsearch/cluster/block/ClusterBlocks.java b/server/src/main/java/org/elasticsearch/cluster/block/ClusterBlocks.java index 736f7f9379efd..1d610b339de2f 100644 --- a/server/src/main/java/org/elasticsearch/cluster/block/ClusterBlocks.java +++ b/server/src/main/java/org/elasticsearch/cluster/block/ClusterBlocks.java @@ -72,6 +72,8 @@ public Set global() { return global; } + // Review note: project-aware flavor of global() used in TransportSearch and TransportFieldCaps + // which were already project-aware public Set global(ProjectId projectId) { return Sets.union(global, projectBlocks(projectId).projectGlobals()); } @@ -96,6 +98,8 @@ public Set global(ClusterBlockLevel level) { return levelHolders.get(level).global(); } + // For a specific project, global could be either project global or cluster global + // Review note: changed TransportAddIndexBlock to use this since it is project-aware public Set global(ProjectId projectId, ClusterBlockLevel level) { var levelHolder = levelHolders.get(level); return Sets.union(levelHolder.global, levelHolder.projects.getOrDefault(projectId, ProjectBlocks.EMPTY).projectGlobals()); @@ -159,6 +163,9 @@ public boolean disableStatePersistence() { return false; } + // Review note: seems to be used only with STATE_NOT_RECOVERED by different node-level services. May or may not need to + // consider project globals once/if we have a project block that is similar to STATE_NOT_RECOVERED for project creation/resurrection + // time (essentially something similar to PROJECT_UNDER_DELETION_BLOCK, but retryable). public boolean hasGlobalBlock(ClusterBlock block) { return global.contains(block); } @@ -172,10 +179,16 @@ public boolean hasGlobalBlockWithId(final int blockId) { return false; } + // Review note: used by monitoring/localExporter and watcher, both currently not project aware. public boolean hasGlobalBlockWithLevel(ClusterBlockLevel level) { return global(level).size() > 0; } + // Review note: Used by TransportAbstractBulk which is already project-aware + public boolean hasGlobalBlockWithLevel(ProjectId projectId, ClusterBlockLevel level) { + return global(projectId, level).size() > 0; + } + /** * Is there a global block with the provided status? */ @@ -194,6 +207,7 @@ public boolean hasIndexBlock(String index, ClusterBlock block) { return hasIndexBlock(Metadata.DEFAULT_PROJECT_ID, index, block); } + // Review note: Not changing index-specific checks. public boolean hasIndexBlock(ProjectId projectId, String index, ClusterBlock block) { final var projectBlocks = projectBlocksMap.get(projectId); if (projectBlocks == null) { @@ -206,6 +220,7 @@ public boolean hasIndexBlock(ProjectId projectId, String index, ClusterBlock blo return clusterBlocks.contains(block); } + // Review note: Not changing index-specific checks. public boolean hasIndexBlockLevel(ProjectId projectId, String index, ClusterBlockLevel level) { return blocksForIndex(projectId, level, index).isEmpty() == false; } @@ -214,6 +229,7 @@ public boolean hasIndexBlockWithId(ProjectId projectId, String index, int blockI return getIndexBlockWithId(projectId, index, blockId) != null; } + // Review note: Not changing index-specific checks. @Nullable public ClusterBlock getIndexBlockWithId(final ProjectId projectId, final String index, final int blockId) { final var projectBlocks = projectBlocksMap.get(projectId); @@ -230,6 +246,7 @@ public ClusterBlock getIndexBlockWithId(final ProjectId projectId, final String return null; } + // Review note: only a watcher action uses this since it is not project-aware public void globalBlockedRaiseException(ClusterBlockLevel level) throws ClusterBlockException { ClusterBlockException blockException = globalBlockedException(level); if (blockException != null) { @@ -237,6 +254,14 @@ public void globalBlockedRaiseException(ClusterBlockLevel level) throws ClusterB } } + // Review note: All new callers seemed project-aware/scoped actions. + public void globalBlockedRaiseException(ProjectId projectId, ClusterBlockLevel level) throws ClusterBlockException { + ClusterBlockException blockException = globalBlockedException(projectId, level); + if (blockException != null) { + throw blockException; + } + } + private boolean globalBlocked(ClusterBlockLevel level) { return global(level).isEmpty() == false; } @@ -245,6 +270,10 @@ private boolean globalBlocked(ProjectId projectId, ClusterBlockLevel level) { return global(projectId, level).isEmpty() == false; } + // Review note: this has some 200 callers mostly Transport actions. Not sure but maybe I have to + // review callers and update those that are project-scoped. TransportGetDataStreamLifecycle is one example + // that i've updated here, although many don't seem to be user facing or available + // directly in serverless. Could also be a follow up to update the callers. public ClusterBlockException globalBlockedException(ClusterBlockLevel level) { if (globalBlocked(level) == false) { return null; @@ -252,6 +281,13 @@ public ClusterBlockException globalBlockedException(ClusterBlockLevel level) { return new ClusterBlockException(global(level)); } + public ClusterBlockException globalBlockedException(ProjectId projectId, ClusterBlockLevel level) { + if (globalBlocked(projectId, level) == false) { + return null; + } + return new ClusterBlockException(global(projectId, level)); + } + public void indexBlockedRaiseException(ProjectId projectId, ClusterBlockLevel level, String index) throws ClusterBlockException { // Not throw for multi-project for now to avoid wide-spread cascading changes. ClusterBlockException blockException = indexBlockedException(projectId, level, index); diff --git a/server/src/main/java/org/elasticsearch/persistent/UpdatePersistentTaskStatusAction.java b/server/src/main/java/org/elasticsearch/persistent/UpdatePersistentTaskStatusAction.java index 1b308566bb87c..273ea4215250d 100644 --- a/server/src/main/java/org/elasticsearch/persistent/UpdatePersistentTaskStatusAction.java +++ b/server/src/main/java/org/elasticsearch/persistent/UpdatePersistentTaskStatusAction.java @@ -138,7 +138,7 @@ public TransportAction( @Override protected ClusterBlockException checkBlock(Request request, ClusterState state) { // Cluster is not affected but we look up repositories in metadata - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } @Override diff --git a/server/src/test/java/org/elasticsearch/action/search/MultiSearchActionTookTests.java b/server/src/test/java/org/elasticsearch/action/search/MultiSearchActionTookTests.java index 954d57a27bb7b..6bf0d296b90d3 100644 --- a/server/src/test/java/org/elasticsearch/action/search/MultiSearchActionTookTests.java +++ b/server/src/test/java/org/elasticsearch/action/search/MultiSearchActionTookTests.java @@ -15,6 +15,7 @@ import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.node.DiscoveryNodeUtils; +import org.elasticsearch.cluster.project.DefaultProjectResolver; import org.elasticsearch.cluster.project.TestProjectResolvers; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.UUIDs; @@ -172,7 +173,8 @@ public String getLocalNodeId() { clusterService, availableProcessors, expected::get, - client + client, + DefaultProjectResolver.INSTANCE ) { @Override void executeSearch( @@ -193,7 +195,8 @@ void executeSearch( clusterService, availableProcessors, System::nanoTime, - client + client, + DefaultProjectResolver.INSTANCE ) { @Override void executeSearch( diff --git a/server/src/test/java/org/elasticsearch/action/search/TransportMultiSearchActionTests.java b/server/src/test/java/org/elasticsearch/action/search/TransportMultiSearchActionTests.java index 706d3c26fc521..54022e1e9d5f0 100644 --- a/server/src/test/java/org/elasticsearch/action/search/TransportMultiSearchActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/search/TransportMultiSearchActionTests.java @@ -20,6 +20,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodeRole; import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.project.DefaultProjectResolver; import org.elasticsearch.cluster.project.TestProjectResolvers; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Randomness; @@ -107,7 +108,8 @@ public String getLocalNodeId() { clusterService, 10, System::nanoTime, - client + client, + DefaultProjectResolver.INSTANCE ); PlainActionFuture future = new PlainActionFuture<>(); @@ -199,7 +201,8 @@ public String getLocalNodeId() { clusterService, 10, System::nanoTime, - client + client, + DefaultProjectResolver.INSTANCE ); // Execute the multi search api and fail if we find an error after executing: diff --git a/x-pack/plugin/enrich/src/main/java/org/elasticsearch/xpack/enrich/action/TransportDeleteEnrichPolicyAction.java b/x-pack/plugin/enrich/src/main/java/org/elasticsearch/xpack/enrich/action/TransportDeleteEnrichPolicyAction.java index 42956590d0371..81bdcae130792 100644 --- a/x-pack/plugin/enrich/src/main/java/org/elasticsearch/xpack/enrich/action/TransportDeleteEnrichPolicyAction.java +++ b/x-pack/plugin/enrich/src/main/java/org/elasticsearch/xpack/enrich/action/TransportDeleteEnrichPolicyAction.java @@ -185,6 +185,6 @@ private void deletePolicy(ProjectId projectId, String name, ActionListener { private final EnrichPolicyExecutor executor; + private final ProjectResolver projectResolver; @Inject public TransportExecuteEnrichPolicyAction( @@ -40,7 +42,8 @@ public TransportExecuteEnrichPolicyAction( ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters, - EnrichPolicyExecutor enrichPolicyExecutor + EnrichPolicyExecutor enrichPolicyExecutor, + ProjectResolver projectResolver ) { super( ExecuteEnrichPolicyAction.NAME, @@ -53,6 +56,7 @@ public TransportExecuteEnrichPolicyAction( EsExecutors.DIRECT_EXECUTOR_SERVICE ); this.executor = enrichPolicyExecutor; + this.projectResolver = projectResolver; } @Override @@ -67,6 +71,6 @@ protected void masterOperation( @Override protected ClusterBlockException checkBlock(ExecuteEnrichPolicyAction.Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_READ); } } diff --git a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/analytics/action/TransportDeleteAnalyticsCollectionAction.java b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/analytics/action/TransportDeleteAnalyticsCollectionAction.java index 72bfdea0b8186..4b47a5e0deba6 100644 --- a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/analytics/action/TransportDeleteAnalyticsCollectionAction.java +++ b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/analytics/action/TransportDeleteAnalyticsCollectionAction.java @@ -14,6 +14,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.logging.DeprecationCategory; import org.elasticsearch.common.logging.DeprecationLogger; @@ -37,6 +38,7 @@ public class TransportDeleteAnalyticsCollectionAction extends AcknowledgedTransp DeleteAnalyticsCollectionAction.Request> { private final AnalyticsCollectionService analyticsCollectionService; + private final ProjectResolver projectResolver; @Inject public TransportDeleteAnalyticsCollectionAction( @@ -44,7 +46,8 @@ public TransportDeleteAnalyticsCollectionAction( ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters, - AnalyticsCollectionService analyticsCollectionService + AnalyticsCollectionService analyticsCollectionService, + ProjectResolver projectResolver ) { super( DeleteAnalyticsCollectionAction.NAME, @@ -56,11 +59,12 @@ public TransportDeleteAnalyticsCollectionAction( EsExecutors.DIRECT_EXECUTOR_SERVICE ); this.analyticsCollectionService = analyticsCollectionService; + this.projectResolver = projectResolver; } @Override protected ClusterBlockException checkBlock(DeleteAnalyticsCollectionAction.Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } @Override diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/action/TransportDeleteInferenceEndpointAction.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/action/TransportDeleteInferenceEndpointAction.java index 46f4babe5b7cf..d213111d82d9f 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/action/TransportDeleteInferenceEndpointAction.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/action/TransportDeleteInferenceEndpointAction.java @@ -18,6 +18,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.util.concurrent.EsExecutors; @@ -46,6 +47,7 @@ public class TransportDeleteInferenceEndpointAction extends TransportMasterNodeA private final ModelRegistry modelRegistry; private final InferenceServiceRegistry serviceRegistry; private final Executor executor; + private final ProjectResolver projectResolver; @Inject public TransportDeleteInferenceEndpointAction( @@ -54,7 +56,8 @@ public TransportDeleteInferenceEndpointAction( ThreadPool threadPool, ActionFilters actionFilters, ModelRegistry modelRegistry, - InferenceServiceRegistry serviceRegistry + InferenceServiceRegistry serviceRegistry, + ProjectResolver projectResolver ) { super( DeleteInferenceEndpointAction.NAME, @@ -69,6 +72,7 @@ public TransportDeleteInferenceEndpointAction( this.modelRegistry = modelRegistry; this.serviceRegistry = serviceRegistry; this.executor = threadPool.executor(UTILITY_THREAD_POOL_NAME); + this.projectResolver = projectResolver; } @Override @@ -230,7 +234,7 @@ private static Set endpointIsReferencedInPipelines(final ClusterState st @Override protected ClusterBlockException checkBlock(DeleteInferenceEndpointAction.Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.WRITE); } } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/action/TransportDeleteInferenceEndpointActionTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/action/TransportDeleteInferenceEndpointActionTests.java index b015eade0ecfe..f57b62ac1c8bf 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/action/TransportDeleteInferenceEndpointActionTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/action/TransportDeleteInferenceEndpointActionTests.java @@ -12,6 +12,7 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.project.TestProjectResolvers; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.core.TimeValue; import org.elasticsearch.inference.InferenceService; @@ -59,7 +60,8 @@ public void setUp() throws Exception { threadPool, mock(ActionFilters.class), mockModelRegistry, - mockInferenceServiceRegistry + mockInferenceServiceRegistry, + TestProjectResolvers.DEFAULT_PROJECT_ONLY ); } diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDataFrameAnalyticsAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDataFrameAnalyticsAction.java index da0c5d4d6efea..567865da426af 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDataFrameAnalyticsAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDataFrameAnalyticsAction.java @@ -17,6 +17,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.injection.guice.Inject; @@ -53,6 +54,7 @@ public class TransportDeleteDataFrameAnalyticsAction extends AcknowledgedTranspo private final MlMemoryTracker memoryTracker; private final DataFrameAnalyticsConfigProvider configProvider; private final DataFrameAnalyticsAuditor auditor; + private final ProjectResolver projectResolver; @Inject public TransportDeleteDataFrameAnalyticsAction( @@ -63,7 +65,8 @@ public TransportDeleteDataFrameAnalyticsAction( Client client, MlMemoryTracker memoryTracker, DataFrameAnalyticsConfigProvider configProvider, - DataFrameAnalyticsAuditor auditor + DataFrameAnalyticsAuditor auditor, + ProjectResolver projectResolver ) { super( DeleteDataFrameAnalyticsAction.NAME, @@ -78,6 +81,7 @@ public TransportDeleteDataFrameAnalyticsAction( this.memoryTracker = memoryTracker; this.configProvider = configProvider; this.auditor = Objects.requireNonNull(auditor); + this.projectResolver = Objects.requireNonNull(projectResolver); } @Override @@ -172,6 +176,6 @@ private void normalDelete( @Override protected ClusterBlockException checkBlock(DeleteDataFrameAnalyticsAction.Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } } diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDatafeedAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDatafeedAction.java index 715d9bb1d0785..3030b98c8246d 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDatafeedAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteDatafeedAction.java @@ -15,6 +15,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.injection.guice.Inject; @@ -38,6 +39,7 @@ public class TransportDeleteDatafeedAction extends AcknowledgedTransportMasterNo private final Client client; private final DatafeedManager datafeedManager; private final PersistentTasksService persistentTasksService; + private final ProjectResolver projectResolver; @Inject public TransportDeleteDatafeedAction( @@ -47,7 +49,8 @@ public TransportDeleteDatafeedAction( ActionFilters actionFilters, Client client, PersistentTasksService persistentTasksService, - DatafeedManager datafeedManager + DatafeedManager datafeedManager, + ProjectResolver projectResolver ) { super( DeleteDatafeedAction.NAME, @@ -61,6 +64,7 @@ public TransportDeleteDatafeedAction( this.client = client; this.persistentTasksService = persistentTasksService; this.datafeedManager = datafeedManager; + this.projectResolver = projectResolver; } @Override @@ -126,6 +130,6 @@ public void onFailure(Exception e) { @Override protected ClusterBlockException checkBlock(DeleteDatafeedAction.Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } } diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteJobAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteJobAction.java index 348f9181313ae..9b3bef1e33d11 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteJobAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteJobAction.java @@ -21,6 +21,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.core.Nullable; @@ -72,6 +73,7 @@ public class TransportDeleteJobAction extends AcknowledgedTransportMasterNodeAct private final JobManager jobManager; private final DatafeedConfigProvider datafeedConfigProvider; private final MlMemoryTracker memoryTracker; + private final ProjectResolver projectResolver; /** * A map of task listeners by job_id. @@ -93,7 +95,8 @@ public TransportDeleteJobAction( JobConfigProvider jobConfigProvider, DatafeedConfigProvider datafeedConfigProvider, MlMemoryTracker memoryTracker, - JobManager jobManager + JobManager jobManager, + ProjectResolver projectResolver ) { super( DeleteJobAction.NAME, @@ -112,11 +115,12 @@ public TransportDeleteJobAction( this.memoryTracker = memoryTracker; this.listenersByJobId = new HashMap<>(); this.jobManager = jobManager; + this.projectResolver = projectResolver; } @Override protected ClusterBlockException checkBlock(DeleteJobAction.Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } @Override diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAction.java index 7ad733aa7443e..c6719aa9b00b6 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAction.java @@ -22,6 +22,7 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.core.SuppressForbidden; @@ -67,6 +68,7 @@ public class TransportDeleteTrainedModelAction extends AcknowledgedTransportMast private final TrainedModelProvider trainedModelProvider; private final InferenceAuditor auditor; private final IngestService ingestService; + private final ProjectResolver projectResolver; @Inject public TransportDeleteTrainedModelAction( @@ -77,7 +79,8 @@ public TransportDeleteTrainedModelAction( ActionFilters actionFilters, TrainedModelProvider configProvider, InferenceAuditor auditor, - IngestService ingestService + IngestService ingestService, + ProjectResolver projectResolver ) { super( DeleteTrainedModelAction.NAME, @@ -92,6 +95,7 @@ public TransportDeleteTrainedModelAction( this.trainedModelProvider = configProvider; this.ingestService = ingestService; this.auditor = Objects.requireNonNull(auditor); + this.projectResolver = projectResolver; } @Override @@ -289,6 +293,6 @@ private static void executeTaskCancellation( @Override protected ClusterBlockException checkBlock(DeleteTrainedModelAction.Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } } diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAliasAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAliasAction.java index 2b8baa9075ced..cc46942f2272b 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAliasAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAliasAction.java @@ -19,6 +19,7 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.core.SuppressForbidden; @@ -45,6 +46,7 @@ public class TransportDeleteTrainedModelAliasAction extends AcknowledgedTranspor private final InferenceAuditor auditor; private final IngestService ingestService; + private final ProjectResolver projectResolver; @Inject public TransportDeleteTrainedModelAliasAction( @@ -53,7 +55,8 @@ public TransportDeleteTrainedModelAliasAction( ThreadPool threadPool, ActionFilters actionFilters, InferenceAuditor auditor, - IngestService ingestService + IngestService ingestService, + ProjectResolver projectResolver ) { super( DeleteTrainedModelAliasAction.NAME, @@ -66,6 +69,7 @@ public TransportDeleteTrainedModelAliasAction( ); this.auditor = auditor; this.ingestService = ingestService; + this.projectResolver = projectResolver; } @Override @@ -128,6 +132,6 @@ static ClusterState deleteModelAlias( @Override protected ClusterBlockException checkBlock(DeleteTrainedModelAliasAction.Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); } } diff --git a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/action/TransportMonitoringBulkAction.java b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/action/TransportMonitoringBulkAction.java index 78ad42dbcbb65..cdb000a1808e8 100644 --- a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/action/TransportMonitoringBulkAction.java +++ b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/action/TransportMonitoringBulkAction.java @@ -15,6 +15,7 @@ import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.util.concurrent.EsExecutors; +import org.elasticsearch.core.FixForMultiProject; import org.elasticsearch.injection.guice.Inject; import org.elasticsearch.tasks.Task; import org.elasticsearch.threadpool.ThreadPool; @@ -57,6 +58,7 @@ public TransportMonitoringBulkAction( } @Override + @FixForMultiProject(description = "Once/if this action becomes project-aware, it must consider project blocks as well") protected void doExecute(Task task, MonitoringBulkRequest request, ActionListener listener) { clusterService.state().blocks().globalBlockedRaiseException(ClusterBlockLevel.WRITE); diff --git a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporter.java b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporter.java index 024b3dc1e52dc..24b8aa7491335 100644 --- a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporter.java +++ b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporter.java @@ -27,6 +27,7 @@ import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.time.DateFormatter; import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.core.FixForMultiProject; import org.elasticsearch.core.Nullable; import org.elasticsearch.core.TimeValue; import org.elasticsearch.gateway.GatewayService; @@ -75,6 +76,9 @@ import static org.elasticsearch.xpack.core.ClientHelper.MONITORING_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; +@FixForMultiProject( + description = "Once/if this becomes project-aware, it must consider project blocks when using ClusterBlocks.hasGlobalBlockWithLevel" +) public final class LocalExporter extends Exporter implements ClusterStateListener, CleanerService.Listener, LicenseStateListener { private static final Logger logger = LogManager.getLogger(LocalExporter.class); diff --git a/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/action/TransportDeleteTransformAction.java b/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/action/TransportDeleteTransformAction.java index d2cfdeac28867..34305a5597175 100644 --- a/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/action/TransportDeleteTransformAction.java +++ b/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/action/TransportDeleteTransformAction.java @@ -23,6 +23,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.core.TimeValue; @@ -59,6 +60,7 @@ public class TransportDeleteTransformAction extends AcknowledgedTransportMasterN private final TransformConfigManager transformConfigManager; private final TransformAuditor auditor; private final Client client; + private final ProjectResolver projectResolver; @Inject public TransportDeleteTransformAction( @@ -67,7 +69,8 @@ public TransportDeleteTransformAction( ThreadPool threadPool, ClusterService clusterService, TransformServices transformServices, - Client client + Client client, + ProjectResolver projectResolver ) { super( DeleteTransformAction.NAME, @@ -81,6 +84,7 @@ public TransportDeleteTransformAction( this.transformConfigManager = transformServices.configManager(); this.auditor = transformServices.auditor(); this.client = client; + this.projectResolver = projectResolver; } @Override @@ -240,6 +244,6 @@ private static void findDestinationIndexInAliases(GetAliasesResponse aliases, St @Override protected ClusterBlockException checkBlock(Request request, ClusterState state) { - return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ); + return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_READ); } } From d0f5583628b73864b450194ef82a524b679420de Mon Sep 17 00:00:00 2001 From: Pooya Salehi Date: Mon, 16 Jun 2025 11:45:46 +0200 Subject: [PATCH 2/3] cleanup --- .../cluster/block/ClusterBlocks.java | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/block/ClusterBlocks.java b/server/src/main/java/org/elasticsearch/cluster/block/ClusterBlocks.java index 1d610b339de2f..0212e45958f7f 100644 --- a/server/src/main/java/org/elasticsearch/cluster/block/ClusterBlocks.java +++ b/server/src/main/java/org/elasticsearch/cluster/block/ClusterBlocks.java @@ -72,8 +72,7 @@ public Set global() { return global; } - // Review note: project-aware flavor of global() used in TransportSearch and TransportFieldCaps - // which were already project-aware + // Project-aware flavor of global() used to find global or project-global blocks for a specific project. public Set global(ProjectId projectId) { return Sets.union(global, projectBlocks(projectId).projectGlobals()); } @@ -99,7 +98,6 @@ public Set global(ClusterBlockLevel level) { } // For a specific project, global could be either project global or cluster global - // Review note: changed TransportAddIndexBlock to use this since it is project-aware public Set global(ProjectId projectId, ClusterBlockLevel level) { var levelHolder = levelHolders.get(level); return Sets.union(levelHolder.global, levelHolder.projects.getOrDefault(projectId, ProjectBlocks.EMPTY).projectGlobals()); @@ -163,9 +161,6 @@ public boolean disableStatePersistence() { return false; } - // Review note: seems to be used only with STATE_NOT_RECOVERED by different node-level services. May or may not need to - // consider project globals once/if we have a project block that is similar to STATE_NOT_RECOVERED for project creation/resurrection - // time (essentially something similar to PROJECT_UNDER_DELETION_BLOCK, but retryable). public boolean hasGlobalBlock(ClusterBlock block) { return global.contains(block); } @@ -179,12 +174,10 @@ public boolean hasGlobalBlockWithId(final int blockId) { return false; } - // Review note: used by monitoring/localExporter and watcher, both currently not project aware. public boolean hasGlobalBlockWithLevel(ClusterBlockLevel level) { return global(level).size() > 0; } - // Review note: Used by TransportAbstractBulk which is already project-aware public boolean hasGlobalBlockWithLevel(ProjectId projectId, ClusterBlockLevel level) { return global(projectId, level).size() > 0; } @@ -207,7 +200,6 @@ public boolean hasIndexBlock(String index, ClusterBlock block) { return hasIndexBlock(Metadata.DEFAULT_PROJECT_ID, index, block); } - // Review note: Not changing index-specific checks. public boolean hasIndexBlock(ProjectId projectId, String index, ClusterBlock block) { final var projectBlocks = projectBlocksMap.get(projectId); if (projectBlocks == null) { @@ -220,7 +212,6 @@ public boolean hasIndexBlock(ProjectId projectId, String index, ClusterBlock blo return clusterBlocks.contains(block); } - // Review note: Not changing index-specific checks. public boolean hasIndexBlockLevel(ProjectId projectId, String index, ClusterBlockLevel level) { return blocksForIndex(projectId, level, index).isEmpty() == false; } @@ -229,7 +220,6 @@ public boolean hasIndexBlockWithId(ProjectId projectId, String index, int blockI return getIndexBlockWithId(projectId, index, blockId) != null; } - // Review note: Not changing index-specific checks. @Nullable public ClusterBlock getIndexBlockWithId(final ProjectId projectId, final String index, final int blockId) { final var projectBlocks = projectBlocksMap.get(projectId); @@ -246,7 +236,6 @@ public ClusterBlock getIndexBlockWithId(final ProjectId projectId, final String return null; } - // Review note: only a watcher action uses this since it is not project-aware public void globalBlockedRaiseException(ClusterBlockLevel level) throws ClusterBlockException { ClusterBlockException blockException = globalBlockedException(level); if (blockException != null) { @@ -254,7 +243,6 @@ public void globalBlockedRaiseException(ClusterBlockLevel level) throws ClusterB } } - // Review note: All new callers seemed project-aware/scoped actions. public void globalBlockedRaiseException(ProjectId projectId, ClusterBlockLevel level) throws ClusterBlockException { ClusterBlockException blockException = globalBlockedException(projectId, level); if (blockException != null) { @@ -270,10 +258,6 @@ private boolean globalBlocked(ProjectId projectId, ClusterBlockLevel level) { return global(projectId, level).isEmpty() == false; } - // Review note: this has some 200 callers mostly Transport actions. Not sure but maybe I have to - // review callers and update those that are project-scoped. TransportGetDataStreamLifecycle is one example - // that i've updated here, although many don't seem to be user facing or available - // directly in serverless. Could also be a follow up to update the callers. public ClusterBlockException globalBlockedException(ClusterBlockLevel level) { if (globalBlocked(level) == false) { return null; From a99cea1a2b2191d46c8c0c14cd8870aec7d4c7ab Mon Sep 17 00:00:00 2001 From: Pooya Salehi Date: Tue, 17 Jun 2025 11:25:26 +0200 Subject: [PATCH 3/3] address review comments --- .../template/get/TransportGetComponentTemplateAction.java | 4 +--- .../action/ingest/GetPipelineTransportAction.java | 7 +------ .../persistent/UpdatePersistentTaskStatusAction.java | 2 +- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComponentTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComponentTemplateAction.java index 5ca4a1ebd618a..7e885f1f80e24 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComponentTemplateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComponentTemplateAction.java @@ -38,7 +38,6 @@ public class TransportGetComponentTemplateAction extends TransportLocalProjectMe GetComponentTemplateAction.Response> { private final ClusterSettings clusterSettings; - private final ProjectResolver projectResolver; /** * NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC it must be registered with the TransportService until @@ -62,7 +61,6 @@ public TransportGetComponentTemplateAction( projectResolver ); clusterSettings = clusterService.getClusterSettings(); - this.projectResolver = projectResolver; transportService.registerRequestHandler( actionName, executor, @@ -75,7 +73,7 @@ public TransportGetComponentTemplateAction( @Override protected ClusterBlockException checkBlock(GetComponentTemplateAction.Request request, ProjectState state) { - return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_READ); + return state.blocks().globalBlockedException(state.projectId(), ClusterBlockLevel.METADATA_READ); } @Override diff --git a/server/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java b/server/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java index 6608cb3d9bb52..dbfccab83bf2d 100644 --- a/server/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java +++ b/server/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java @@ -26,9 +26,6 @@ import org.elasticsearch.transport.TransportService; public class GetPipelineTransportAction extends TransportLocalProjectMetadataAction { - - private final ProjectResolver projectResolver; - /** * NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC it must be registered with the TransportService until * we no longer need to support calling this action remotely. @@ -51,8 +48,6 @@ public GetPipelineTransportAction( projectResolver ); - this.projectResolver = projectResolver; - transportService.registerRequestHandler( actionName, executor, @@ -75,7 +70,7 @@ protected void localClusterStateOperation( @Override protected ClusterBlockException checkBlock(GetPipelineRequest request, ProjectState state) { - return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_READ); + return state.blocks().globalBlockedException(state.projectId(), ClusterBlockLevel.METADATA_READ); } } diff --git a/server/src/main/java/org/elasticsearch/persistent/UpdatePersistentTaskStatusAction.java b/server/src/main/java/org/elasticsearch/persistent/UpdatePersistentTaskStatusAction.java index 273ea4215250d..1b308566bb87c 100644 --- a/server/src/main/java/org/elasticsearch/persistent/UpdatePersistentTaskStatusAction.java +++ b/server/src/main/java/org/elasticsearch/persistent/UpdatePersistentTaskStatusAction.java @@ -138,7 +138,7 @@ public TransportAction( @Override protected ClusterBlockException checkBlock(Request request, ClusterState state) { // Cluster is not affected but we look up repositories in metadata - return state.blocks().globalBlockedException(projectResolver.getProjectId(), ClusterBlockLevel.METADATA_WRITE); + return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); } @Override