Skip to content

Commit 4506be6

Browse files
[8.17][ML] Fix .inference index leaking out of tests. (elastic#115310)
* [ML] Do not create the .inference index as a side effect of calling usage (elastic#115023) The Inference usage API calls GET _inference/_all and because the default configs are persisted on read it causes the creation of the .inference index. This action is undesirable and causes test failures by leaking the system index out of the test clean up code. # Conflicts: # muted-tests.yml # x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/action/TransportGetInferenceModelAction.java * unmute tests * precommit * spotless --------- Co-authored-by: Elastic Machine <[email protected]>
1 parent 552a438 commit 4506be6

File tree

7 files changed

+131
-76
lines changed

7 files changed

+131
-76
lines changed

muted-tests.yml

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -321,80 +321,26 @@ tests:
321321
- class: org.elasticsearch.xpack.inference.TextEmbeddingCrudIT
322322
method: testPutE5WithTrainedModelAndInference
323323
issue: https://github.com/elastic/elasticsearch/issues/114023
324-
- class: org.elasticsearch.xpack.enrich.EnrichRestIT
325-
method: test {p0=enrich/40_synthetic_source/enrich documents over _bulk}
326-
issue: https://github.com/elastic/elasticsearch/issues/114825
327324
- class: org.elasticsearch.threadpool.SimpleThreadPoolIT
328325
method: testThreadPoolMetrics
329326
issue: https://github.com/elastic/elasticsearch/issues/108320
330-
- class: org.elasticsearch.xpack.eql.EqlRestValidationIT
331-
method: testDefaultIndicesOptions
332-
issue: https://github.com/elastic/elasticsearch/issues/114771
333-
- class: org.elasticsearch.xpack.enrich.EnrichRestIT
334-
method: test {p0=enrich/10_basic/Test enrich crud apis}
335-
issue: https://github.com/elastic/elasticsearch/issues/114766
336327
- class: org.elasticsearch.xpack.inference.TextEmbeddingCrudIT
337328
method: testPutE5Small_withPlatformAgnosticVariant
338329
issue: https://github.com/elastic/elasticsearch/issues/113983
339-
- class: org.elasticsearch.xpack.eql.EqlRestIT
340-
method: testIndexWildcardPatterns
341-
issue: https://github.com/elastic/elasticsearch/issues/114749
342-
- class: org.elasticsearch.xpack.enrich.EnrichRestIT
343-
method: test {p0=enrich/20_standard_index/enrich stats REST response structure}
344-
issue: https://github.com/elastic/elasticsearch/issues/114753
345330
- class: org.elasticsearch.ingest.geoip.DatabaseNodeServiceIT
346331
method: testGzippedDatabase
347332
issue: https://github.com/elastic/elasticsearch/issues/113752
348-
- class: org.elasticsearch.xpack.enrich.EnrichRestIT
349-
method: test {p0=enrich/10_basic/Test using the deprecated elasticsearch_version field results in a warning}
350-
issue: https://github.com/elastic/elasticsearch/issues/114748
351-
- class: org.elasticsearch.xpack.enrich.EnrichRestIT
352-
method: test {p0=enrich/20_standard_index/enrich documents over _bulk via an alias}
353-
issue: https://github.com/elastic/elasticsearch/issues/114763
354-
- class: org.elasticsearch.xpack.eql.EqlRestValidationIT
355-
method: testAllowNoIndicesOption
356-
issue: https://github.com/elastic/elasticsearch/issues/114789
357-
- class: org.elasticsearch.xpack.enrich.EnrichRestIT
358-
method: test {p0=enrich/20_standard_index/enrich documents over _bulk}
359-
issue: https://github.com/elastic/elasticsearch/issues/114768
360333
- class: org.elasticsearch.datastreams.LazyRolloverDuringDisruptionIT
361334
method: testRolloverIsExecutedOnce
362335
issue: https://github.com/elastic/elasticsearch/issues/112634
363-
- class: org.elasticsearch.xpack.eql.EqlStatsIT
364-
method: testEqlRestUsage
365-
issue: https://github.com/elastic/elasticsearch/issues/114790
366-
- class: org.elasticsearch.xpack.eql.EqlRestIT
367-
method: testBadRequests
368-
issue: https://github.com/elastic/elasticsearch/issues/114752
369-
- class: org.elasticsearch.xpack.eql.EqlRestIT
370-
method: testUnicodeChars
371-
issue: https://github.com/elastic/elasticsearch/issues/114791
372336
- class: org.elasticsearch.xpack.rank.rrf.RRFRankClientYamlTestSuiteIT
373337
method: test {yaml=rrf/800_rrf_with_text_similarity_reranker_retriever/explain using rrf retriever and text-similarity}
374338
issue: https://github.com/elastic/elasticsearch/issues/114757
375-
- class: org.elasticsearch.xpack.enrich.EnrichRestIT
376-
method: test {p0=enrich/50_data_stream/enrich documents over _bulk via a data stream}
377-
issue: https://github.com/elastic/elasticsearch/issues/114769
378339
- class: org.elasticsearch.xpack.remotecluster.RemoteClusterSecurityWithApmTracingRestIT
379340
method: testTracingCrossCluster
380341
issue: https://github.com/elastic/elasticsearch/issues/112731
381342
- class: org.elasticsearch.license.LicensingTests
382343
issue: https://github.com/elastic/elasticsearch/issues/114865
383-
- class: org.elasticsearch.xpack.enrich.EnrichIT
384-
method: testImmutablePolicy
385-
issue: https://github.com/elastic/elasticsearch/issues/114839
386-
- class: org.elasticsearch.xpack.enrich.EnrichIT
387-
method: testDeleteIsCaseSensitive
388-
issue: https://github.com/elastic/elasticsearch/issues/114840
389-
- class: org.elasticsearch.xpack.enrich.EnrichRestIT
390-
method: test {p0=enrich/30_tsdb_index/enrich documents over _bulk}
391-
issue: https://github.com/elastic/elasticsearch/issues/114761
392-
- class: org.elasticsearch.xpack.enrich.EnrichIT
393-
method: testDeleteExistingPipeline
394-
issue: https://github.com/elastic/elasticsearch/issues/114775
395-
- class: org.elasticsearch.xpack.enrich.EnrichIT
396-
method: testEnrichSpecialTypes
397-
issue: https://github.com/elastic/elasticsearch/issues/114773
398344
- class: org.elasticsearch.xpack.inference.TextEmbeddingCrudIT
399345
method: testPutE5Small_withPlatformSpecificVariant
400346
issue: https://github.com/elastic/elasticsearch/issues/113950

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/inference/action/GetInferenceModelAction.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,40 @@ public GetInferenceModelAction() {
3434

3535
public static class Request extends AcknowledgedRequest<GetInferenceModelAction.Request> {
3636

37+
private static boolean PERSIST_DEFAULT_CONFIGS = true;
38+
3739
private final String inferenceEntityId;
3840
private final TaskType taskType;
41+
// Default endpoint configurations are persisted on first read.
42+
// Set to false to avoid persisting on read.
43+
// This setting only applies to GET * requests. It has
44+
// no effect when getting a single model
45+
private final boolean persistDefaultConfig;
3946

4047
public Request(String inferenceEntityId, TaskType taskType) {
4148
super(TRAPPY_IMPLICIT_DEFAULT_MASTER_NODE_TIMEOUT, DEFAULT_ACK_TIMEOUT);
4249
this.inferenceEntityId = Objects.requireNonNull(inferenceEntityId);
4350
this.taskType = Objects.requireNonNull(taskType);
51+
this.persistDefaultConfig = PERSIST_DEFAULT_CONFIGS;
52+
}
53+
54+
public Request(String inferenceEntityId, TaskType taskType, boolean persistDefaultConfig) {
55+
super(TRAPPY_IMPLICIT_DEFAULT_MASTER_NODE_TIMEOUT, DEFAULT_ACK_TIMEOUT);
56+
this.inferenceEntityId = Objects.requireNonNull(inferenceEntityId);
57+
this.taskType = Objects.requireNonNull(taskType);
58+
this.persistDefaultConfig = persistDefaultConfig;
4459
}
4560

4661
public Request(StreamInput in) throws IOException {
4762
super(in);
4863
this.inferenceEntityId = in.readString();
4964
this.taskType = TaskType.fromStream(in);
65+
if (in.getTransportVersion().onOrAfter(TransportVersions.INFERENCE_DONT_PERSIST_ON_READ)) {
66+
this.persistDefaultConfig = in.readBoolean();
67+
} else {
68+
this.persistDefaultConfig = PERSIST_DEFAULT_CONFIGS;
69+
}
70+
5071
}
5172

5273
public String getInferenceEntityId() {
@@ -57,24 +78,33 @@ public TaskType getTaskType() {
5778
return taskType;
5879
}
5980

81+
public boolean isPersistDefaultConfig() {
82+
return persistDefaultConfig;
83+
}
84+
6085
@Override
6186
public void writeTo(StreamOutput out) throws IOException {
6287
super.writeTo(out);
6388
out.writeString(inferenceEntityId);
6489
taskType.writeTo(out);
90+
if (out.getTransportVersion().onOrAfter(TransportVersions.INFERENCE_DONT_PERSIST_ON_READ)) {
91+
out.writeBoolean(this.persistDefaultConfig);
92+
}
6593
}
6694

6795
@Override
6896
public boolean equals(Object o) {
6997
if (this == o) return true;
7098
if (o == null || getClass() != o.getClass()) return false;
7199
Request request = (Request) o;
72-
return Objects.equals(inferenceEntityId, request.inferenceEntityId) && taskType == request.taskType;
100+
return Objects.equals(inferenceEntityId, request.inferenceEntityId)
101+
&& taskType == request.taskType
102+
&& persistDefaultConfig == request.persistDefaultConfig;
73103
}
74104

75105
@Override
76106
public int hashCode() {
77-
return Objects.hash(inferenceEntityId, taskType);
107+
return Objects.hash(inferenceEntityId, taskType, persistDefaultConfig);
78108
}
79109
}
80110

x-pack/plugin/inference/src/internalClusterTest/java/org/elasticsearch/xpack/inference/integration/ModelRegistryIT.java

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.cluster.service.ClusterService;
1515
import org.elasticsearch.common.io.stream.StreamOutput;
1616
import org.elasticsearch.common.settings.Settings;
17+
import org.elasticsearch.index.IndexNotFoundException;
1718
import org.elasticsearch.inference.InferenceService;
1819
import org.elasticsearch.inference.InferenceServiceExtension;
1920
import org.elasticsearch.inference.Model;
@@ -250,7 +251,7 @@ public void testGetAllModels() throws InterruptedException {
250251
}
251252

252253
AtomicReference<List<UnparsedModel>> modelHolder = new AtomicReference<>();
253-
blockingCall(listener -> modelRegistry.getAllModels(listener), modelHolder, exceptionHolder);
254+
blockingCall(listener -> modelRegistry.getAllModels(randomBoolean(), listener), modelHolder, exceptionHolder);
254255
assertNull(exceptionHolder.get());
255256
assertThat(modelHolder.get(), hasSize(modelCount));
256257
var getAllModels = modelHolder.get();
@@ -332,14 +333,14 @@ public void testGetAllModels_WithDefaults() throws Exception {
332333
}
333334

334335
AtomicReference<List<UnparsedModel>> modelHolder = new AtomicReference<>();
335-
blockingCall(listener -> modelRegistry.getAllModels(listener), modelHolder, exceptionHolder);
336+
blockingCall(listener -> modelRegistry.getAllModels(randomBoolean(), listener), modelHolder, exceptionHolder);
336337
assertNull(exceptionHolder.get());
337338
assertThat(modelHolder.get(), hasSize(totalModelCount));
338339
var getAllModels = modelHolder.get();
339340
assertReturnModelIsModifiable(modelHolder.get().get(0));
340341

341342
// same result but configs should have been persisted this time
342-
blockingCall(listener -> modelRegistry.getAllModels(listener), modelHolder, exceptionHolder);
343+
blockingCall(listener -> modelRegistry.getAllModels(randomBoolean(), listener), modelHolder, exceptionHolder);
343344
assertNull(exceptionHolder.get());
344345
assertThat(modelHolder.get(), hasSize(totalModelCount));
345346

@@ -386,7 +387,7 @@ public void testGetAllModels_OnlyDefaults() throws Exception {
386387

387388
AtomicReference<Exception> exceptionHolder = new AtomicReference<>();
388389
AtomicReference<List<UnparsedModel>> modelHolder = new AtomicReference<>();
389-
blockingCall(listener -> modelRegistry.getAllModels(listener), modelHolder, exceptionHolder);
390+
blockingCall(listener -> modelRegistry.getAllModels(randomBoolean(), listener), modelHolder, exceptionHolder);
390391
assertNull(exceptionHolder.get());
391392
assertThat(modelHolder.get(), hasSize(2));
392393
var getAllModels = modelHolder.get();
@@ -404,6 +405,44 @@ public void testGetAllModels_OnlyDefaults() throws Exception {
404405
}
405406
}
406407

408+
public void testGetAllModels_withDoNotPersist() throws Exception {
409+
int defaultModelCount = 2;
410+
var serviceName = "foo";
411+
var service = mock(InferenceService.class);
412+
413+
var defaultConfigs = new ArrayList<Model>();
414+
var defaultIds = new ArrayList<InferenceService.DefaultConfigId>();
415+
for (int i = 0; i < defaultModelCount; i++) {
416+
var id = "default-" + i;
417+
var taskType = randomFrom(TaskType.values());
418+
defaultConfigs.add(createModel(id, taskType, serviceName));
419+
defaultIds.add(new InferenceService.DefaultConfigId(id, taskType, service));
420+
}
421+
422+
doAnswer(invocation -> {
423+
@SuppressWarnings("unchecked")
424+
var listener = (ActionListener<List<Model>>) invocation.getArguments()[0];
425+
listener.onResponse(defaultConfigs);
426+
return Void.TYPE;
427+
}).when(service).defaultConfigs(any());
428+
429+
defaultIds.forEach(modelRegistry::addDefaultIds);
430+
431+
AtomicReference<Exception> exceptionHolder = new AtomicReference<>();
432+
AtomicReference<List<UnparsedModel>> modelHolder = new AtomicReference<>();
433+
blockingCall(listener -> modelRegistry.getAllModels(false, listener), modelHolder, exceptionHolder);
434+
assertNull(exceptionHolder.get());
435+
assertThat(modelHolder.get(), hasSize(2));
436+
437+
expectThrows(IndexNotFoundException.class, () -> client().admin().indices().prepareGetIndex().addIndices(".inference").get());
438+
439+
// this time check the index is created
440+
blockingCall(listener -> modelRegistry.getAllModels(true, listener), modelHolder, exceptionHolder);
441+
assertNull(exceptionHolder.get());
442+
assertThat(modelHolder.get(), hasSize(2));
443+
assertInferenceIndexExists();
444+
}
445+
407446
public void testGet_WithDefaults() throws InterruptedException {
408447
var serviceName = "foo";
409448
var service = mock(InferenceService.class);
@@ -512,6 +551,12 @@ public void testGetByTaskType_WithDefaults() throws Exception {
512551
assertReturnModelIsModifiable(modelHolder.get().get(0));
513552
}
514553

554+
private void assertInferenceIndexExists() {
555+
var indexResponse = client().admin().indices().prepareGetIndex().addIndices(".inference").get();
556+
assertNotNull(indexResponse.getSettings());
557+
assertNotNull(indexResponse.getMappings());
558+
}
559+
515560
@SuppressWarnings("unchecked")
516561
private void assertReturnModelIsModifiable(UnparsedModel unparsedModel) {
517562
var settings = unparsedModel.settings();
@@ -550,7 +595,6 @@ private Model buildElserModelConfig(String inferenceEntityId, TaskType taskType)
550595
);
551596
default -> throw new IllegalArgumentException("task type " + taskType + " is not supported");
552597
};
553-
554598
}
555599

556600
protected <T> void blockingCall(Consumer<ActionListener<T>> function, AtomicReference<T> response, AtomicReference<Exception> error)

x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/action/TransportGetInferenceModelAction.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ protected void doExecute(
7272
boolean inferenceEntityIdIsWildCard = Strings.isAllOrWildcard(request.getInferenceEntityId());
7373

7474
if (request.getTaskType() == TaskType.ANY && inferenceEntityIdIsWildCard) {
75-
getAllModels(listener);
75+
getAllModels(request.isPersistDefaultConfig(), listener);
7676
} else if (inferenceEntityIdIsWildCard) {
7777
getModelsByTaskType(request.getTaskType(), listener);
7878
} else {
@@ -114,8 +114,11 @@ private void getSingleModel(
114114
}));
115115
}
116116

117-
private void getAllModels(ActionListener<GetInferenceModelAction.Response> listener) {
118-
modelRegistry.getAllModels(listener.delegateFailureAndWrap((l, models) -> executor.execute(() -> parseModels(models, listener))));
117+
private void getAllModels(boolean persistDefaultEndpoints, ActionListener<GetInferenceModelAction.Response> listener) {
118+
modelRegistry.getAllModels(
119+
persistDefaultEndpoints,
120+
listener.delegateFailureAndWrap((l, models) -> executor.execute(() -> parseModels(models, listener)))
121+
);
119122
}
120123

121124
private void getModelsByTaskType(TaskType taskType, ActionListener<GetInferenceModelAction.Response> listener) {

x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/action/TransportInferenceUsageAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ protected void masterOperation(
6363
ClusterState state,
6464
ActionListener<XPackUsageFeatureResponse> listener
6565
) {
66-
GetInferenceModelAction.Request getInferenceModelAction = new GetInferenceModelAction.Request("_all", TaskType.ANY);
66+
GetInferenceModelAction.Request getInferenceModelAction = new GetInferenceModelAction.Request("_all", TaskType.ANY, false);
6767
client.execute(GetInferenceModelAction.INSTANCE, getInferenceModelAction, listener.delegateFailureAndWrap((delegate, response) -> {
6868
Map<String, InferenceFeatureSetUsage.ModelStats> stats = new TreeMap<>();
6969
for (ModelConfigurations model : response.getEndpoints()) {

0 commit comments

Comments
 (0)