Skip to content

Commit e4fe9c5

Browse files
committed
[CPS] Create Cross Project IndicesOptions
An initial IndicesOptions for CrossProject. This will be used to identify when the index must be resolved for a cross-project search. It currently always defaults to false so we can start reading the value, and a later commit will handle enabling it.
1 parent 945517b commit e4fe9c5

File tree

6 files changed

+93
-10
lines changed

6 files changed

+93
-10
lines changed

server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ protected ClusterBlockException checkBlock(RolloverRequest request, ClusterState
159159
.matchOpen(request.indicesOptions().expandWildcardsOpen())
160160
.matchClosed(request.indicesOptions().expandWildcardsClosed())
161161
.build(),
162-
IndicesOptions.GatekeeperOptions.DEFAULT
162+
IndicesOptions.GatekeeperOptions.DEFAULT,
163+
IndicesOptions.ResolutionModeOptions.DEFAULT
163164
);
164165
ResolvedExpression resolvedRolloverTarget = SelectorResolver.parseExpression(request.getRolloverTarget(), request.indicesOptions());
165166
final IndexAbstraction indexAbstraction = projectMetadata.getIndicesLookup().get(resolvedRolloverTarget.resource());
@@ -255,7 +256,8 @@ protected void masterOperation(
255256
final var statsIndicesOptions = new IndicesOptions(
256257
IndicesOptions.ConcreteTargetOptions.ALLOW_UNAVAILABLE_TARGETS,
257258
IndicesOptions.WildcardOptions.builder().matchClosed(true).allowEmptyExpressions(false).build(),
258-
IndicesOptions.GatekeeperOptions.DEFAULT
259+
IndicesOptions.GatekeeperOptions.DEFAULT,
260+
IndicesOptions.ResolutionModeOptions.DEFAULT
259261
);
260262
// Make sure to recombine any selectors on the stats request
261263
IndicesStatsRequest statsRequest = new IndicesStatsRequest().indices(resolvedRolloverTarget.combined())

server/src/main/java/org/elasticsearch/action/support/IndicesOptions.java

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
package org.elasticsearch.action.support;
1010

1111
import org.elasticsearch.ElasticsearchParseException;
12+
import org.elasticsearch.TransportVersion;
1213
import org.elasticsearch.TransportVersions;
1314
import org.elasticsearch.common.io.stream.StreamInput;
1415
import org.elasticsearch.common.io.stream.StreamOutput;
16+
import org.elasticsearch.common.io.stream.Writeable;
1517
import org.elasticsearch.common.logging.DeprecationCategory;
1618
import org.elasticsearch.common.logging.DeprecationLogger;
1719
import org.elasticsearch.core.Nullable;
@@ -49,7 +51,8 @@
4951
public record IndicesOptions(
5052
ConcreteTargetOptions concreteTargetOptions,
5153
WildcardOptions wildcardOptions,
52-
GatekeeperOptions gatekeeperOptions
54+
GatekeeperOptions gatekeeperOptions,
55+
ResolutionModeOptions resolutionModeOptions
5356
) implements ToXContentFragment {
5457

5558
public static IndicesOptions.Builder builder() {
@@ -413,6 +416,37 @@ public static Builder builder(GatekeeperOptions gatekeeperOptions) {
413416
}
414417
}
415418

419+
public record ResolutionModeOptions(boolean crossProject) implements ToXContentFragment, Writeable {
420+
421+
public static final ResolutionModeOptions DEFAULT = new ResolutionModeOptions(false);
422+
423+
private static final TransportVersion INDICES_OPTIONS_RESOLUTION_MODE = TransportVersion.fromName(
424+
"indices_options_resolution_mode"
425+
);
426+
427+
private static final String CROSS_PROJECT_NAME = "resolve_cross_project";
428+
429+
@Override
430+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
431+
return builder.field(CROSS_PROJECT_NAME, crossProject);
432+
}
433+
434+
@Override
435+
public void writeTo(StreamOutput out) throws IOException {
436+
if (out.getTransportVersion().supports(INDICES_OPTIONS_RESOLUTION_MODE)) {
437+
out.writeBoolean(crossProject);
438+
}
439+
}
440+
441+
public static ResolutionModeOptions readFrom(StreamInput in) throws IOException {
442+
if (in.getTransportVersion().supports(INDICES_OPTIONS_RESOLUTION_MODE)) {
443+
return new ResolutionModeOptions(in.readBoolean());
444+
} else {
445+
return ResolutionModeOptions.DEFAULT;
446+
}
447+
}
448+
}
449+
416450
/**
417451
* This class is maintained for backwards compatibility and performance purposes. We use it for serialisation along with {@link Option}.
418452
*/
@@ -463,7 +497,8 @@ private enum Option {
463497
public static final IndicesOptions DEFAULT = new IndicesOptions(
464498
ConcreteTargetOptions.ERROR_WHEN_UNAVAILABLE_TARGETS,
465499
WildcardOptions.DEFAULT,
466-
GatekeeperOptions.DEFAULT
500+
GatekeeperOptions.DEFAULT,
501+
ResolutionModeOptions.DEFAULT
467502
);
468503

469504
public static final IndicesOptions STRICT_EXPAND_OPEN = IndicesOptions.builder()
@@ -857,6 +892,13 @@ public boolean ignoreThrottled() {
857892
return gatekeeperOptions().ignoreThrottled();
858893
}
859894

895+
/**
896+
* @return whether indices will resolve to the cross-project "flat world" expression
897+
*/
898+
public boolean resolveCrossProject() {
899+
return resolutionModeOptions().crossProject();
900+
}
901+
860902
public void writeIndicesOptions(StreamOutput out) throws IOException {
861903
EnumSet<Option> backwardsCompatibleOptions = EnumSet.noneOf(Option.class);
862904
if (allowNoIndices()) {
@@ -917,6 +959,7 @@ public void writeIndicesOptions(StreamOutput out) throws IOException {
917959
out.writeByte((byte) 0); // ordinal 0 (::data selector)
918960
}
919961
}
962+
out.writeWriteable(resolutionModeOptions);
920963
}
921964

922965
public static IndicesOptions readIndicesOptions(StreamInput in) throws IOException {
@@ -968,14 +1011,16 @@ public static IndicesOptions readIndicesOptions(StreamInput in) throws IOExcepti
9681011
? ConcreteTargetOptions.ALLOW_UNAVAILABLE_TARGETS
9691012
: ConcreteTargetOptions.ERROR_WHEN_UNAVAILABLE_TARGETS,
9701013
wildcardOptions,
971-
gatekeeperOptions
1014+
gatekeeperOptions,
1015+
ResolutionModeOptions.readFrom(in)
9721016
);
9731017
}
9741018

9751019
public static class Builder {
9761020
private ConcreteTargetOptions concreteTargetOptions;
9771021
private WildcardOptions wildcardOptions;
9781022
private GatekeeperOptions gatekeeperOptions;
1023+
private ResolutionModeOptions resolutionModeOptions;
9791024

9801025
Builder() {
9811026
this(DEFAULT);
@@ -985,6 +1030,7 @@ public static class Builder {
9851030
concreteTargetOptions = indicesOptions.concreteTargetOptions;
9861031
wildcardOptions = indicesOptions.wildcardOptions;
9871032
gatekeeperOptions = indicesOptions.gatekeeperOptions;
1033+
resolutionModeOptions = indicesOptions.resolutionModeOptions;
9881034
}
9891035

9901036
public Builder concreteTargetOptions(ConcreteTargetOptions concreteTargetOptions) {
@@ -1012,8 +1058,13 @@ public Builder gatekeeperOptions(GatekeeperOptions.Builder generalOptions) {
10121058
return this;
10131059
}
10141060

1061+
public Builder resolutionModeOptions(ResolutionModeOptions resolutionModeOptions) {
1062+
this.resolutionModeOptions = resolutionModeOptions;
1063+
return this;
1064+
}
1065+
10151066
public IndicesOptions build() {
1016-
return new IndicesOptions(concreteTargetOptions, wildcardOptions, gatekeeperOptions);
1067+
return new IndicesOptions(concreteTargetOptions, wildcardOptions, gatekeeperOptions, resolutionModeOptions);
10171068
}
10181069
}
10191070

@@ -1115,7 +1166,8 @@ public static IndicesOptions fromOptions(
11151166
return new IndicesOptions(
11161167
ignoreUnavailable ? ConcreteTargetOptions.ALLOW_UNAVAILABLE_TARGETS : ConcreteTargetOptions.ERROR_WHEN_UNAVAILABLE_TARGETS,
11171168
wildcards,
1118-
gatekeeperOptions
1169+
gatekeeperOptions,
1170+
ResolutionModeOptions.DEFAULT
11191171
);
11201172
}
11211173

@@ -1202,13 +1254,15 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par
12021254
concreteTargetOptions.toXContent(builder, params);
12031255
wildcardOptions.toXContent(builder, params);
12041256
gatekeeperOptions.toXContent(builder, params);
1257+
resolutionModeOptions.toXContent(builder, params);
12051258
return builder;
12061259
}
12071260

12081261
private static final ParseField EXPAND_WILDCARDS_FIELD = new ParseField(WildcardOptions.EXPAND_WILDCARDS);
12091262
private static final ParseField IGNORE_UNAVAILABLE_FIELD = new ParseField(ConcreteTargetOptions.IGNORE_UNAVAILABLE);
12101263
private static final ParseField IGNORE_THROTTLED_FIELD = new ParseField(GatekeeperOptions.IGNORE_THROTTLED).withAllDeprecated();
12111264
private static final ParseField ALLOW_NO_INDICES_FIELD = new ParseField(WildcardOptions.ALLOW_NO_INDICES);
1265+
private static final ParseField RESOLVE_CROSS_PROJECT = new ParseField(ResolutionModeOptions.CROSS_PROJECT_NAME);
12121266

12131267
public static IndicesOptions fromXContent(XContentParser parser) throws IOException {
12141268
return fromXContent(parser, null);
@@ -1221,6 +1275,7 @@ public static IndicesOptions fromXContent(XContentParser parser, @Nullable Indic
12211275
.ignoreThrottled(defaults != null && defaults.gatekeeperOptions().ignoreThrottled());
12221276
Boolean allowNoIndices = defaults == null ? null : defaults.allowNoIndices();
12231277
Boolean ignoreUnavailable = defaults == null ? null : defaults.ignoreUnavailable();
1278+
boolean resolveCrossProject = defaults == null ? ResolutionModeOptions.DEFAULT.crossProject() : defaults.resolveCrossProject();
12241279
Token token = parser.currentToken() == Token.START_OBJECT ? parser.currentToken() : parser.nextToken();
12251280
String currentFieldName = null;
12261281
if (token != Token.START_OBJECT) {
@@ -1268,6 +1323,8 @@ public static IndicesOptions fromXContent(XContentParser parser, @Nullable Indic
12681323
allowNoIndices = parser.booleanValue();
12691324
} else if (IGNORE_THROTTLED_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
12701325
generalOptions.ignoreThrottled(parser.booleanValue());
1326+
} else if (RESOLVE_CROSS_PROJECT.match(currentFieldName, parser.getDeprecationHandler())) {
1327+
resolveCrossProject = parser.booleanValue();
12711328
} else {
12721329
throw new ElasticsearchParseException(
12731330
"could not read indices options. Unexpected index option [" + currentFieldName + "]"
@@ -1298,6 +1355,7 @@ public static IndicesOptions fromXContent(XContentParser parser, @Nullable Indic
12981355
.concreteTargetOptions(new ConcreteTargetOptions(ignoreUnavailable))
12991356
.wildcardOptions(wildcards)
13001357
.gatekeeperOptions(generalOptions)
1358+
.resolutionModeOptions(new ResolutionModeOptions(resolveCrossProject))
13011359
.build();
13021360
}
13031361

@@ -1459,6 +1517,8 @@ public String toString() {
14591517
+ allowSelectors()
14601518
+ ", include_failure_indices="
14611519
+ includeFailureIndices()
1520+
+ ", resolve_cross_project="
1521+
+ resolveCrossProject()
14621522
+ ']';
14631523
}
14641524
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
9173000
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
index_reshard_shardcount_summary,9172000
1+
indices_options_resolution_mode,9173000

server/src/test/java/org/elasticsearch/action/support/IndicesOptionsTests.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import org.elasticsearch.action.support.IndicesOptions.ConcreteTargetOptions;
1313
import org.elasticsearch.action.support.IndicesOptions.GatekeeperOptions;
14+
import org.elasticsearch.action.support.IndicesOptions.ResolutionModeOptions;
1415
import org.elasticsearch.action.support.IndicesOptions.WildcardOptions;
1516
import org.elasticsearch.common.bytes.BytesReference;
1617
import org.elasticsearch.common.io.stream.BytesStreamOutput;
@@ -57,6 +58,7 @@ public void testSerialization() throws Exception {
5758
.allowClosedIndices(randomBoolean())
5859
.allowSelectors(randomBoolean())
5960
)
61+
.resolutionModeOptions(new ResolutionModeOptions(randomBoolean()))
6062
.build();
6163

6264
BytesStreamOutput output = new BytesStreamOutput();
@@ -102,6 +104,7 @@ public void testFromOptions() {
102104
assertThat(indicesOptions.forbidClosedIndices(), equalTo(forbidClosedIndices));
103105
assertEquals(ignoreAliases, indicesOptions.ignoreAliases());
104106
assertEquals(ignoreThrottled, indicesOptions.ignoreThrottled());
107+
assertEquals(indicesOptions.resolveCrossProject(), ResolutionModeOptions.DEFAULT.crossProject());
105108
}
106109

107110
public void testFromOptionsWithDefaultOptions() {
@@ -138,6 +141,7 @@ public void testFromOptionsWithDefaultOptions() {
138141
assertEquals(defaultOptions.allowAliasesToMultipleIndices(), indicesOptions.allowAliasesToMultipleIndices());
139142
assertEquals(defaultOptions.forbidClosedIndices(), indicesOptions.forbidClosedIndices());
140143
assertEquals(defaultOptions.ignoreAliases(), indicesOptions.ignoreAliases());
144+
assertEquals(defaultOptions.resolveCrossProject(), indicesOptions.resolveCrossProject());
141145
}
142146

143147
public void testFromParameters() {
@@ -201,6 +205,7 @@ public void testFromParameters() {
201205
assertEquals(defaultOptions.allowAliasesToMultipleIndices(), updatedOptions.allowAliasesToMultipleIndices());
202206
assertEquals(defaultOptions.forbidClosedIndices(), updatedOptions.forbidClosedIndices());
203207
assertEquals(defaultOptions.ignoreAliases(), updatedOptions.ignoreAliases());
208+
assertEquals(defaultOptions.resolveCrossProject(), updatedOptions.resolveCrossProject());
204209
}
205210

206211
public void testEqualityAndHashCode() {
@@ -330,6 +335,7 @@ public void testFromMap() {
330335
assertEquals(ignoreUnavailable == null ? defaults.ignoreUnavailable() : ignoreUnavailable, fromMap.ignoreUnavailable());
331336
assertEquals(allowNoIndices == null ? defaults.allowNoIndices() : allowNoIndices, fromMap.allowNoIndices());
332337
assertEquals(ignoreThrottled == null ? defaults.ignoreThrottled() : ignoreThrottled, fromMap.ignoreThrottled());
338+
assertEquals(fromMap.resolveCrossProject(), ResolutionModeOptions.DEFAULT.crossProject());
333339
}
334340

335341
public void testToXContent() throws IOException {
@@ -348,8 +354,14 @@ public void testToXContent() throws IOException {
348354
randomBoolean(),
349355
randomBoolean()
350356
);
357+
ResolutionModeOptions resolutionModeOptions = new ResolutionModeOptions(randomBoolean());
351358

352-
IndicesOptions indicesOptions = new IndicesOptions(concreteTargetOptions, wildcardOptions, gatekeeperOptions);
359+
IndicesOptions indicesOptions = new IndicesOptions(
360+
concreteTargetOptions,
361+
wildcardOptions,
362+
gatekeeperOptions,
363+
resolutionModeOptions
364+
);
353365

354366
XContentType type = randomFrom(XContentType.values());
355367
BytesReference xContentBytes = toXContentBytes(indicesOptions, type);
@@ -364,6 +376,7 @@ public void testToXContent() throws IOException {
364376
assertThat(map.get("ignore_unavailable"), equalTo(concreteTargetOptions.allowUnavailableTargets()));
365377
assertThat(map.get("allow_no_indices"), equalTo(wildcardOptions.allowEmptyExpressions()));
366378
assertThat(map.get("ignore_throttled"), equalTo(gatekeeperOptions.ignoreThrottled()));
379+
assertThat(map.get("resolve_cross_project"), equalTo(resolutionModeOptions.crossProject()));
367380
}
368381

369382
public void testFromXContent() throws IOException {
@@ -375,10 +388,12 @@ public void testFromXContent() throws IOException {
375388
randomBoolean()
376389
);
377390
ConcreteTargetOptions concreteTargetOptions = new ConcreteTargetOptions(randomBoolean());
391+
ResolutionModeOptions resolutionModeOptions = new ResolutionModeOptions(randomBoolean());
378392

379393
IndicesOptions indicesOptions = IndicesOptions.builder()
380394
.concreteTargetOptions(concreteTargetOptions)
381395
.wildcardOptions(wildcardOptions)
396+
.resolutionModeOptions(resolutionModeOptions)
382397
.build();
383398

384399
XContentType type = randomFrom(XContentType.values());
@@ -397,6 +412,7 @@ public void testFromXContent() throws IOException {
397412
assertEquals(indicesOptions.ignoreUnavailable(), fromXContentOptions.ignoreUnavailable());
398413
assertEquals(indicesOptions.allowNoIndices(), fromXContentOptions.allowNoIndices());
399414
assertEquals(indicesOptions.ignoreThrottled(), fromXContentOptions.ignoreThrottled());
415+
assertEquals(indicesOptions.resolveCrossProject(), fromXContentOptions.resolveCrossProject());
400416
}
401417

402418
public void testFromXContentWithWildcardSpecialValues() throws IOException {
@@ -423,6 +439,7 @@ public void testFromXContentWithWildcardSpecialValues() throws IOException {
423439
assertTrue(fromXContentOptions.expandWildcardsClosed());
424440
assertTrue(fromXContentOptions.expandWildcardsHidden());
425441
assertTrue(fromXContentOptions.expandWildcardsOpen());
442+
assertFalse(fromXContentOptions.resolveCrossProject());
426443

427444
try (XContentBuilder builder = XContentFactory.contentBuilder(type)) {
428445
builder.startObject();
@@ -441,6 +458,7 @@ public void testFromXContentWithWildcardSpecialValues() throws IOException {
441458
assertFalse(fromXContentOptions.expandWildcardsClosed());
442459
assertFalse(fromXContentOptions.expandWildcardsHidden());
443460
assertFalse(fromXContentOptions.expandWildcardsOpen());
461+
assertFalse(fromXContentOptions.resolveCrossProject());
444462
}
445463

446464
public void testFromXContentWithDefaults() throws Exception {
@@ -494,6 +512,7 @@ public void testFromXContentWithDefaults() throws Exception {
494512
}
495513
assertEquals(ignoreUnavailable, fromXContentOptions.ignoreUnavailable());
496514
assertEquals(expectedWildcardStates, fromXContentOptions.wildcardOptions());
515+
assertFalse(fromXContentOptions.resolveCrossProject());
497516
}
498517

499518
private BytesReference toXContentBytes(IndicesOptions indicesOptions, XContentType type) throws IOException {

server/src/test/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolverTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2371,7 +2371,8 @@ public void testIgnoreThrottled() {
23712371
new IndicesOptions(
23722372
IndicesOptions.ConcreteTargetOptions.ERROR_WHEN_UNAVAILABLE_TARGETS,
23732373
IndicesOptions.WildcardOptions.DEFAULT,
2374-
IndicesOptions.GatekeeperOptions.builder().ignoreThrottled(true).build()
2374+
IndicesOptions.GatekeeperOptions.builder().ignoreThrottled(true).build(),
2375+
IndicesOptions.ResolutionModeOptions.DEFAULT
23752376
),
23762377
"ind*",
23772378
"test-index"

0 commit comments

Comments
 (0)