-
Notifications
You must be signed in to change notification settings - Fork 25.5k
POC: Cross-Project Search #131168
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
POC: Cross-Project Search #131168
Changes from 22 commits
980723e
4ff5e6e
3df7a1d
c21a0a9
5266376
650dd77
9d63d77
8eec08e
fe6b696
8dee748
f9d6407
be2ab99
710d789
3587e6a
26a49c0
2a45f5b
9d29d4f
0ef2258
88104ce
035ffc1
f5cad57
fe3dea0
1153dfa
3fd532e
512222e
b867e69
08d3e4e
d36c3f6
d20a8c9
32ed394
67f5cdf
e25d8b2
137195f
ee93568
18d6bcb
2ae90af
2b092fb
d834784
7de6de0
9e53cc3
2d8a118
01ad89b
4cc41c3
254977c
e427303
efbd82e
d8103f9
1d3dc40
c03c73a
1f04a53
9f341be
7c6b1fc
91bf747
266a822
bf307e2
768affc
d1bd040
a78010b
ca5b153
aaab227
1967bfa
700af92
652caf3
3a8c4dc
24b9f7c
804069c
a61ad84
ab675dc
b11d30a
cd6511f
da74cb5
5373143
6544589
7b7aa7d
2af9134
c17b5c5
7d9a438
80bd89e
0a4046c
49814b1
01276d5
d1bb772
d5af5bc
f380e82
fd1df71
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the "Elastic License | ||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
* Public License v 1"; you may not use this file except in compliance with, at | ||
* your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
* License v3.0 only", or the "Server Side Public License, v 1". | ||
*/ | ||
|
||
package org.elasticsearch; | ||
|
||
import org.elasticsearch.action.IndicesRequest; | ||
import org.elasticsearch.transport.RemoteClusterService; | ||
|
||
import java.util.List; | ||
|
||
public interface RewritableIndicesRequest extends IndicesRequest { | ||
boolean rewritten(); | ||
|
||
void rewritten(List<RewrittenIndexExpression> indexExpressions); | ||
|
||
boolean checkRemote(List<RemoteClusterService.RemoteTag> tags); | ||
|
||
record RewrittenIndexExpression(String original, List<String> rewritten) {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,8 @@ | |
|
||
package org.elasticsearch.rest.action.search; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.elasticsearch.ExceptionsHelper; | ||
import org.elasticsearch.action.ActionRequestValidationException; | ||
import org.elasticsearch.action.search.SearchRequest; | ||
|
@@ -35,6 +37,7 @@ | |
import org.elasticsearch.search.sort.SortOrder; | ||
import org.elasticsearch.search.suggest.SuggestBuilder; | ||
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder; | ||
import org.elasticsearch.transport.RemoteClusterService; | ||
import org.elasticsearch.usage.SearchUsageHolder; | ||
import org.elasticsearch.xcontent.XContentParser; | ||
|
||
|
@@ -63,6 +66,7 @@ public class RestSearchAction extends BaseRestHandler { | |
public static final String TYPED_KEYS_PARAM = "typed_keys"; | ||
public static final String INCLUDE_NAMED_QUERIES_SCORE_PARAM = "include_named_queries_score"; | ||
public static final Set<String> RESPONSE_PARAMS = Set.of(TYPED_KEYS_PARAM, TOTAL_HITS_AS_INT_PARAM, INCLUDE_NAMED_QUERIES_SCORE_PARAM); | ||
private static final Logger log = LogManager.getLogger(RestSearchAction.class); | ||
|
||
private final SearchUsageHolder searchUsageHolder; | ||
private final Predicate<NodeFeature> clusterSupportsFeature; | ||
|
@@ -98,6 +102,7 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC | |
client.threadPool().getThreadContext().setErrorTraceTransportHeader(request); | ||
} | ||
SearchRequest searchRequest = new SearchRequest(); | ||
|
||
// access the BwC param, but just drop it | ||
// this might be set by old clients | ||
request.param("min_compatible_shard_node"); | ||
|
@@ -167,6 +172,16 @@ public static void parseSearchRequest( | |
searchRequest.source(new SearchSourceBuilder()); | ||
} | ||
searchRequest.indices(Strings.splitStringByCommaToArray(request.param("index"))); | ||
|
||
var routingTags = request.param("query_routing", null); | ||
if (routingTags != null) { | ||
searchRequest.routingTags( | ||
Arrays.stream(Strings.splitStringByCommaToArray(routingTags)).map(RemoteClusterService.RemoteTag::fromString).toList() | ||
); | ||
|
||
} else { | ||
log.info("No routing tags"); | ||
} | ||
|
||
if (requestContentParser != null) { | ||
if (searchUsageHolder == null) { | ||
searchRequest.source().parseXContent(requestContentParser, true, clusterSupportsFeature); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,7 @@ | |
import java.io.IOException; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
|
@@ -97,6 +98,33 @@ public final class RemoteClusterService extends RemoteClusterAware | |
(ns, key) -> boolSetting(key, true, new RemoteConnectionEnabled<>(ns, key), Setting.Property.Dynamic, Setting.Property.NodeScope) | ||
); | ||
|
||
public record RemoteTag(String key, String value) { | ||
|
||
public static RemoteTag fromString(String tag) { | ||
if (tag == null || tag.isEmpty()) { | ||
throw new IllegalArgumentException("Remote tag must not be null or empty"); | ||
} | ||
// - as a separator to simplify search path param parsing; won't be like this in the real implementation | ||
int idx = tag.indexOf('-'); | ||
if (idx < 0) { | ||
return new RemoteTag(tag, ""); | ||
} else { | ||
return new RemoteTag(tag.substring(0, idx), tag.substring(idx + 1)); | ||
} | ||
} | ||
} | ||
|
||
public static final Setting.AffixSetting<List<RemoteTag>> REMOTE_CLUSTER_TAGS = Setting.affixKeySetting( | ||
"cluster.remote.", | ||
"tags", | ||
(ns, key) -> Setting.listSetting( | ||
key, | ||
Collections.emptyList(), | ||
RemoteTag::fromString, | ||
Setting.Property.Dynamic, | ||
Setting.Property.NodeScope | ||
) | ||
); | ||
|
||
public static final Setting.AffixSetting<TimeValue> REMOTE_CLUSTER_PING_SCHEDULE = Setting.affixKeySetting( | ||
"cluster.remote.", | ||
"transport.ping_schedule", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.core.security; | ||
|
||
import org.elasticsearch.transport.Transport; | ||
import org.elasticsearch.transport.TransportInterceptor; | ||
import org.elasticsearch.transport.TransportRequest; | ||
import org.elasticsearch.transport.TransportRequestOptions; | ||
import org.elasticsearch.transport.TransportResponse; | ||
import org.elasticsearch.transport.TransportResponseHandler; | ||
|
||
public interface CustomRemoteServerTransportInterceptor { | ||
// TODO probably don't want this | ||
boolean enabled(); | ||
|
||
// TODO this should be a wrapper around TransportInterceptor.AsyncSender instead | ||
<T extends TransportResponse> void sendRequest( | ||
TransportInterceptor.AsyncSender sender, | ||
Transport.Connection connection, | ||
String action, | ||
TransportRequest request, | ||
TransportRequestOptions options, | ||
TransportResponseHandler<T> handler | ||
); | ||
|
||
CustomServerTransportFilter getFilter(); | ||
|
||
class Default implements CustomRemoteServerTransportInterceptor { | ||
@Override | ||
public boolean enabled() { | ||
return false; | ||
} | ||
|
||
@Override | ||
public <T extends TransportResponse> void sendRequest( | ||
TransportInterceptor.AsyncSender sender, | ||
Transport.Connection connection, | ||
String action, | ||
TransportRequest request, | ||
TransportRequestOptions options, | ||
TransportResponseHandler<T> handler | ||
) { | ||
sender.sendRequest(connection, action, request, options, handler); | ||
} | ||
|
||
@Override | ||
public CustomServerTransportFilter getFilter() { | ||
return new CustomServerTransportFilter.Default(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.core.security; | ||
|
||
import org.elasticsearch.action.ActionListener; | ||
import org.elasticsearch.transport.TransportRequest; | ||
|
||
public interface CustomServerTransportFilter { | ||
void filter(String securityAction, TransportRequest request, ActionListener<Void> authenticationListener); | ||
|
||
class Default implements CustomServerTransportFilter { | ||
@Override | ||
public void filter(String securityAction, TransportRequest request, ActionListener<Void> listener) { | ||
listener.onResponse(null); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.core.security.authz; | ||
|
||
import org.elasticsearch.RewritableIndicesRequest; | ||
|
||
public interface CustomIndicesRequestRewriter { | ||
void rewrite(RewritableIndicesRequest request); | ||
|
||
class Default implements CustomIndicesRequestRewriter { | ||
@Override | ||
public void rewrite(RewritableIndicesRequest request) { | ||
// No rewriting by default | ||
// This is a no-op implementation | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we also need to check (and track) whether each component of the
rewritten
list is flat or qualified? Is that left for a later impl or do you think we don't need to track that here?