Skip to content

Commit 4d46265

Browse files
authored
[ML] Check Search Inference ID Usage When Deleting An Inference Endpoint (#113895) (#114012)
1 parent f057ff7 commit 4d46265

File tree

3 files changed

+59
-20
lines changed

3 files changed

+59
-20
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/utils/SemanticTextInfoExtractor.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,11 @@ public static Set<String> extractIndexesReferencingInferenceEndpoints(Metadata m
3333
Map<String, IndexMetadata> indices = metadata.indices();
3434

3535
indices.forEach((indexName, indexMetadata) -> {
36-
if (indexMetadata.getInferenceFields() != null) {
37-
Map<String, InferenceFieldMetadata> inferenceFields = indexMetadata.getInferenceFields();
38-
if (inferenceFields.entrySet()
39-
.stream()
40-
.anyMatch(
41-
entry -> entry.getValue().getInferenceId() != null && endpointIds.contains(entry.getValue().getInferenceId())
42-
)) {
43-
referenceIndices.add(indexName);
44-
}
36+
Map<String, InferenceFieldMetadata> inferenceFields = indexMetadata.getInferenceFields();
37+
if (inferenceFields.values()
38+
.stream()
39+
.anyMatch(im -> endpointIds.contains(im.getInferenceId()) || endpointIds.contains(im.getSearchInferenceId()))) {
40+
referenceIndices.add(indexName);
4541
}
4642
});
4743

x-pack/plugin/inference/qa/inference-service-tests/src/javaRestTest/java/org/elasticsearch/xpack/inference/InferenceBaseRestTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,26 @@ protected void putSemanticText(String endpointId, String indexName) throws IOExc
168168
assertOkOrCreated(response);
169169
}
170170

171+
protected void putSemanticText(String endpointId, String searchEndpointId, String indexName) throws IOException {
172+
var request = new Request("PUT", Strings.format("%s", indexName));
173+
String body = Strings.format("""
174+
{
175+
"mappings": {
176+
"properties": {
177+
"inference_field": {
178+
"type": "semantic_text",
179+
"inference_id": "%s",
180+
"search_inference_id": "%s"
181+
}
182+
}
183+
}
184+
}
185+
""", endpointId, searchEndpointId);
186+
request.setJsonEntity(body);
187+
var response = client().performRequest(request);
188+
assertOkOrCreated(response);
189+
}
190+
171191
protected Map<String, Object> putModel(String modelId, String modelConfig, TaskType taskType) throws IOException {
172192
String endpoint = Strings.format("_inference/%s/%s", taskType, modelId);
173193
return putRequest(endpoint, modelConfig);

x-pack/plugin/inference/qa/inference-service-tests/src/javaRestTest/java/org/elasticsearch/xpack/inference/InferenceCrudIT.java

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.io.IOException;
1818
import java.util.List;
1919
import java.util.Set;
20+
import java.util.function.Function;
2021
import java.util.stream.IntStream;
2122
import java.util.stream.Stream;
2223

@@ -154,34 +155,55 @@ public void testDeleteEndpointWhileReferencedByPipeline() throws IOException {
154155
}
155156

156157
public void testDeleteEndpointWhileReferencedBySemanticText() throws IOException {
157-
String endpointId = "endpoint_referenced_by_semantic_text";
158+
final String endpointId = "endpoint_referenced_by_semantic_text";
159+
final String searchEndpointId = "search_endpoint_referenced_by_semantic_text";
160+
final String indexName = randomAlphaOfLength(10).toLowerCase();
161+
final Function<String, String> buildErrorString = endpointName -> " Inference endpoint "
162+
+ endpointName
163+
+ " is being used in the mapping for indexes: "
164+
+ Set.of(indexName)
165+
+ ". Ensure that no index mappings are using this inference endpoint, or use force to ignore this warning and delete the"
166+
+ " inference endpoint.";
167+
158168
putModel(endpointId, mockSparseServiceModelConfig(), TaskType.SPARSE_EMBEDDING);
159-
String indexName = randomAlphaOfLength(10).toLowerCase();
160169
putSemanticText(endpointId, indexName);
161170
{
162-
163-
var errorString = new StringBuilder().append(" Inference endpoint ")
164-
.append(endpointId)
165-
.append(" is being used in the mapping for indexes: ")
166-
.append(Set.of(indexName))
167-
.append(". ")
168-
.append("Ensure that no index mappings are using this inference endpoint, ")
169-
.append("or use force to ignore this warning and delete the inference endpoint.");
170171
var e = expectThrows(ResponseException.class, () -> deleteModel(endpointId));
171-
assertThat(e.getMessage(), containsString(errorString.toString()));
172+
assertThat(e.getMessage(), containsString(buildErrorString.apply(endpointId)));
172173
}
173174
{
174175
var response = deleteModel(endpointId, "dry_run=true");
175176
var entityString = EntityUtils.toString(response.getEntity());
176177
assertThat(entityString, containsString("\"acknowledged\":false"));
177178
assertThat(entityString, containsString(indexName));
179+
assertThat(entityString, containsString(endpointId));
178180
}
179181
{
180182
var response = deleteModel(endpointId, "force=true");
181183
var entityString = EntityUtils.toString(response.getEntity());
182184
assertThat(entityString, containsString("\"acknowledged\":true"));
183185
}
184186
deleteIndex(indexName);
187+
188+
putModel(searchEndpointId, mockSparseServiceModelConfig(), TaskType.SPARSE_EMBEDDING);
189+
putSemanticText(endpointId, searchEndpointId, indexName);
190+
{
191+
var e = expectThrows(ResponseException.class, () -> deleteModel(searchEndpointId));
192+
assertThat(e.getMessage(), containsString(buildErrorString.apply(searchEndpointId)));
193+
}
194+
{
195+
var response = deleteModel(searchEndpointId, "dry_run=true");
196+
var entityString = EntityUtils.toString(response.getEntity());
197+
assertThat(entityString, containsString("\"acknowledged\":false"));
198+
assertThat(entityString, containsString(indexName));
199+
assertThat(entityString, containsString(searchEndpointId));
200+
}
201+
{
202+
var response = deleteModel(searchEndpointId, "force=true");
203+
var entityString = EntityUtils.toString(response.getEntity());
204+
assertThat(entityString, containsString("\"acknowledged\":true"));
205+
}
206+
deleteIndex(indexName);
185207
}
186208

187209
public void testDeleteEndpointWhileReferencedBySemanticTextAndPipeline() throws IOException {
@@ -217,6 +239,7 @@ public void testDeleteEndpointWhileReferencedBySemanticTextAndPipeline() throws
217239
assertThat(entityString, containsString("\"acknowledged\":false"));
218240
assertThat(entityString, containsString(indexName));
219241
assertThat(entityString, containsString(pipelineId));
242+
assertThat(entityString, containsString(endpointId));
220243
}
221244
{
222245
var response = deleteModel(endpointId, "force=true");

0 commit comments

Comments
 (0)