diff --git a/x-pack/plugin/vector-tile/src/main/java/org/elasticsearch/xpack/vectortile/rest/RestVectorTileAction.java b/x-pack/plugin/vector-tile/src/main/java/org/elasticsearch/xpack/vectortile/rest/RestVectorTileAction.java index 442f0176444bd..f14333c8f6328 100644 --- a/x-pack/plugin/vector-tile/src/main/java/org/elasticsearch/xpack/vectortile/rest/RestVectorTileAction.java +++ b/x-pack/plugin/vector-tile/src/main/java/org/elasticsearch/xpack/vectortile/rest/RestVectorTileAction.java @@ -11,6 +11,7 @@ import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.client.internal.node.NodeClient; import org.elasticsearch.common.document.DocumentField; import org.elasticsearch.common.geo.GeoBoundingBox; @@ -45,6 +46,7 @@ import org.elasticsearch.search.aggregations.metrics.InternalGeoBounds; import org.elasticsearch.search.aggregations.pipeline.StatsBucketPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.support.ValuesSourceAggregationBuilder.MetricsAggregationBuilder; +import org.elasticsearch.search.crossproject.CrossProjectModeDecider; import org.elasticsearch.search.fetch.subphase.FieldAndFormat; import org.elasticsearch.search.profile.SearchProfileResults; import org.elasticsearch.search.sort.SortBuilder; @@ -91,10 +93,12 @@ public class RestVectorTileAction extends BaseRestHandler { private final SearchUsageHolder searchUsageHolder; private final Settings settings; + private final CrossProjectModeDecider crossProjectModeDecider; public RestVectorTileAction(SearchUsageHolder searchUsageHolder, Settings settings) { this.searchUsageHolder = searchUsageHolder; this.settings = settings; + this.crossProjectModeDecider = new CrossProjectModeDecider(settings); } @Override @@ -109,15 +113,23 @@ public String getName() { @Override protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException { - if (settings != null && settings.getAsBoolean("serverless.cross_project.enabled", false)) { - // accept but drop project_routing param until fully supported - restRequest.param("project_routing"); - } + boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled(); // This will allow to cancel the search request if the http channel is closed final RestCancellableNodeClient cancellableNodeClient = new RestCancellableNodeClient(client, restRequest.getHttpChannel()); final VectorTileRequest request = VectorTileRequest.parseRestRequest(restRequest, searchUsageHolder::updateUsage); final SearchRequestBuilder searchRequestBuilder = searchRequestBuilder(cancellableNodeClient, request); + + if (crossProjectEnabled && request.allowsCrossProject()) { + searchRequestBuilder.setIndicesOptions( + IndicesOptions.builder(searchRequestBuilder.request().indicesOptions()) + .crossProjectModeOptions(new IndicesOptions.CrossProjectModeOptions(true)) + .build() + ); + } else if (crossProjectEnabled == false && request.getProjectRouting() != null) { + throw new IllegalArgumentException("Unknown key for a VALUE_STRING in [project_routing]"); + } + return channel -> searchRequestBuilder.execute(new RestResponseListener<>(channel) { @Override @@ -288,10 +300,10 @@ private static SearchRequestBuilder searchRequestBuilder(RestCancellableNodeClie for (SortBuilder sortBuilder : request.getSortBuilders()) { searchRequestBuilder.addSort(sortBuilder); } + searchRequestBuilder.request().setProjectRouting(request.getProjectRouting()); return searchRequestBuilder; } - @SuppressWarnings("unchecked") private static VectorTile.Tile.Layer.Builder buildHitsLayer(SearchHit[] hits, VectorTileRequest request, FeatureFactory featureFactory) throws IOException { final VectorTile.Tile.Layer.Builder hitsLayerBuilder = VectorTileUtils.createLayerBuilder(HITS_LAYER, request.getExtent()); diff --git a/x-pack/plugin/vector-tile/src/main/java/org/elasticsearch/xpack/vectortile/rest/VectorTileRequest.java b/x-pack/plugin/vector-tile/src/main/java/org/elasticsearch/xpack/vectortile/rest/VectorTileRequest.java index 69f44d64d6b6d..2638e172c913f 100644 --- a/x-pack/plugin/vector-tile/src/main/java/org/elasticsearch/xpack/vectortile/rest/VectorTileRequest.java +++ b/x-pack/plugin/vector-tile/src/main/java/org/elasticsearch/xpack/vectortile/rest/VectorTileRequest.java @@ -7,9 +7,11 @@ package org.elasticsearch.xpack.vectortile.rest; +import org.elasticsearch.action.IndicesRequest; import org.elasticsearch.common.Strings; import org.elasticsearch.common.geo.SimpleVectorTileFormatter; import org.elasticsearch.core.Booleans; +import org.elasticsearch.core.Nullable; import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.index.query.AbstractQueryBuilder; import org.elasticsearch.index.query.GeoShapeQueryBuilder; @@ -46,7 +48,7 @@ /** * Transforms a rest request in a vector tile request */ -class VectorTileRequest { +class VectorTileRequest implements IndicesRequest.CrossProjectCandidate { protected static final String INDEX_PARAM = "index"; protected static final String FIELD_PARAM = "field"; @@ -61,6 +63,7 @@ class VectorTileRequest { protected static final ParseField BUFFER_FIELD = new ParseField("buffer"); protected static final ParseField EXACT_BOUNDS_FIELD = new ParseField("exact_bounds"); protected static final ParseField WITH_LABELS_FIELD = new ParseField("with_labels"); + protected static final ParseField PROJECT_ROUTING = new ParseField("project_routing"); protected static class Defaults { public static final int SIZE = 10000; @@ -131,6 +134,7 @@ protected static class Defaults { return p.intValue(); } }, SearchSourceBuilder.TRACK_TOTAL_HITS_FIELD, ObjectParser.ValueType.VALUE); + PARSER.declareString(VectorTileRequest::setProjectRouting, PROJECT_ROUTING); } static VectorTileRequest parseRestRequest(RestRequest restRequest, Consumer searchUsageConsumer) throws IOException { @@ -221,6 +225,9 @@ static VectorTileRequest parseRestRequest(RestRequest restRequest, Consumer