Skip to content

Commit 0317c1c

Browse files
jedrazbelasticsearchmachine
andauthored
[Connector API] Support hard deletes with new URL param in delete endpoint (#120200)
* [Connector API] Add hard delete support * Undo accidental change * undo accidental build gradle change * Tweak typos * Update docs/changelog/120200.yaml * [CI] Auto commit changes from spotless * Fix yaml test * Actually skip the feature check since we don't have the feature anyway --------- Co-authored-by: elasticsearchmachine <[email protected]>
1 parent 1ee0be8 commit 0317c1c

File tree

11 files changed

+264
-132
lines changed

11 files changed

+264
-132
lines changed

docs/changelog/120200.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 120200
2+
summary: "[Connector API] Support hard deletes with new URL param in delete endpoint"
3+
area: Extract&Transform
4+
type: feature
5+
issues: []

docs/reference/connector/apis/delete-connector-api.asciidoc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ beta::[]
1313
For the most up-to-date API details, refer to {api-es}/group/endpoint-connector[Connector APIs].
1414
--
1515

16-
Soft-deletes a connector and removes associated sync jobs.
16+
Deletes a connector and optionally removes associated sync jobs.
1717

1818
Note: this action doesn't delete any API key, ingest pipeline or data index associated with the connector. These need to be removed manually.
1919

@@ -37,6 +37,9 @@ To get started with Connector APIs, check out <<es-connectors-tutorial-api, our
3737
`<connector_id>`::
3838
(Required, string)
3939

40+
`<hard>`::
41+
(Optional, boolean) If `true`, the connector doc is deleted. If `false`, connector doc is marked as deleted (soft deletion). Defaults to `false`.
42+
4043
`delete_sync_jobs`::
4144
(Optional, boolean) A flag indicating if associated sync jobs should be also removed. Defaults to `false`.
4245

rest-api-spec/src/main/resources/rest-api-spec/api/connector.delete.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
]
2929
},
3030
"params": {
31+
"hard": {
32+
"type": "boolean",
33+
"default": false,
34+
"description": "If true, the connector doc is deleted. If false, connector doc is marked as deleted (soft-deleted)."
35+
},
3136
"delete_sync_jobs": {
3237
"type": "boolean",
3338
"default": false,

x-pack/plugin/ent-search/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/entsearch/connector/20_connector_list.yml

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,7 @@ setup:
280280

281281
---
282282
"List Connectors - Soft deleted connectors / no deleted":
283-
- requires:
284-
cluster_features: ["connector_soft_deletes"]
285-
reason: Soft deletes were introduced in 9.0 release
283+
286284

287285
- do:
288286
connector.list:
@@ -293,9 +291,7 @@ setup:
293291

294292
---
295293
"List Connectors - Single soft deleted connector":
296-
- requires:
297-
cluster_features: ["connector_soft_deletes"]
298-
reason: Soft deletes were introduced in 9.0 release
294+
299295

300296
- do:
301297
connector.delete:
@@ -312,11 +308,91 @@ setup:
312308

313309
- match: { count: 3 }
314310

311+
312+
---
313+
"List Connectors - Single hard deleted connector":
314+
315+
316+
- do:
317+
connector.delete:
318+
connector_id: connector-a
319+
hard: true
320+
321+
- do:
322+
connector.list: {}
323+
324+
- match: { count: 2 }
325+
326+
- do:
327+
connector.list:
328+
include_deleted: true
329+
330+
- match: { count: 2 }
331+
332+
333+
---
334+
"List Connectors - All hard deleted connectors":
335+
336+
337+
- do:
338+
connector.delete:
339+
connector_id: connector-a
340+
hard: true
341+
342+
- do:
343+
connector.delete:
344+
connector_id: connector-b
345+
hard: true
346+
347+
- do:
348+
connector.delete:
349+
connector_id: connector-c
350+
hard: true
351+
352+
- do:
353+
connector.list: {}
354+
355+
- match: { count: 0 }
356+
357+
- do:
358+
connector.list:
359+
include_deleted: true
360+
361+
- match: { count: 0 }
362+
363+
---
364+
"List Connectors - 2 hard deleted connectors, 1 soft deleted":
365+
366+
367+
- do:
368+
connector.delete:
369+
connector_id: connector-a
370+
hard: false
371+
372+
- do:
373+
connector.delete:
374+
connector_id: connector-b
375+
hard: true
376+
377+
- do:
378+
connector.delete:
379+
connector_id: connector-c
380+
hard: true
381+
382+
- do:
383+
connector.list: {}
384+
385+
- match: { count: 0 }
386+
387+
- do:
388+
connector.list:
389+
include_deleted: true
390+
391+
- match: { count: 1 }
392+
315393
---
316394
"List Connectors - Soft deleted connectors":
317-
- requires:
318-
cluster_features: ["connector_soft_deletes"]
319-
reason: Soft deletes were introduced in 9.0 release
395+
320396

321397
- do:
322398
connector.delete:
@@ -353,9 +429,7 @@ setup:
353429

354430
---
355431
"List Connectors - Soft deleted with from":
356-
- requires:
357-
cluster_features: ["connector_soft_deletes"]
358-
reason: Soft deletes were introduced in 9.0 release
432+
359433

360434
- do:
361435
connector.delete:
@@ -387,9 +461,7 @@ setup:
387461

388462
---
389463
"List Connector - Soft deleted with size":
390-
- requires:
391-
cluster_features: ["connector_soft_deletes"]
392-
reason: Soft deletes were introduced in 9.0 release
464+
393465

394466
- do:
395467
connector.delete:

x-pack/plugin/ent-search/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/entsearch/connector/30_connector_delete.yml

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,31 @@ setup:
2727
connector_id: test-connector-to-delete
2828

2929

30+
---
31+
"Delete Connector - Hard Delete":
32+
- do:
33+
connector.put:
34+
connector_id: test-connector-hard-delete
35+
body:
36+
index_name: search-2-test
37+
name: my-hard-delete-connector
38+
language: en
39+
is_native: false
40+
service_type: super-connector
41+
42+
- do:
43+
connector.delete:
44+
connector_id: test-connector-hard-delete
45+
hard: true
46+
47+
- match: { acknowledged: true }
48+
49+
- do:
50+
catch: "missing"
51+
connector.get:
52+
connector_id: test-connector-hard-delete
53+
include_deleted: true
54+
3055
---
3156
"Delete Connector - deletes associated sync jobs":
3257

@@ -107,12 +132,9 @@ setup:
107132
connector.delete:
108133
connector_id: test-nonexistent-connector
109134

110-
111135
---
112136
"Delete Connector - Supports soft deletes":
113-
- requires:
114-
cluster_features: ["connector_soft_deletes"]
115-
reason: Soft deletes were introduced in 9.0 release
137+
116138

117139
- do:
118140
connector.delete:

x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorIndexService.java

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import org.elasticsearch.action.ActionListener;
1414
import org.elasticsearch.action.DelegatingActionListener;
1515
import org.elasticsearch.action.DocWriteRequest;
16+
import org.elasticsearch.action.DocWriteResponse;
17+
import org.elasticsearch.action.delete.DeleteRequest;
1618
import org.elasticsearch.action.get.GetRequest;
1719
import org.elasticsearch.action.index.IndexRequest;
1820
import org.elasticsearch.action.search.SearchRequest;
@@ -232,40 +234,71 @@ public void getConnector(String connectorId, boolean includeDeleted, ActionListe
232234
}
233235

234236
/**
235-
* Soft deletes the {@link Connector} and optionally removes the related instances of {@link ConnectorSyncJob} in the underlying index.
237+
* Deletes the {@link Connector} and optionally removes the related instances of {@link ConnectorSyncJob} in the underlying index.
236238
*
237239
* @param connectorId The id of the {@link Connector}.
240+
* @param hardDelete If set to true, the {@link Connector} is permanently deleted; otherwise, it is soft-deleted.
238241
* @param shouldDeleteSyncJobs The flag indicating if {@link ConnectorSyncJob} should also be deleted.
239242
* @param listener The action listener to invoke on response/failure.
240243
*/
241-
public void deleteConnector(String connectorId, boolean shouldDeleteSyncJobs, ActionListener<UpdateResponse> listener) {
244+
public void deleteConnector(
245+
String connectorId,
246+
boolean hardDelete,
247+
boolean shouldDeleteSyncJobs,
248+
ActionListener<DocWriteResponse> listener
249+
) {
242250

243251
try {
244-
// ensure that if connector is soft-deleted, deleting it again results in 404
245-
getConnector(connectorId, false, listener.delegateFailure((l, connector) -> {
246-
final UpdateRequest updateRequest = new UpdateRequest(CONNECTOR_INDEX_NAME, connectorId).setRefreshPolicy(
247-
WriteRequest.RefreshPolicy.IMMEDIATE
248-
)
249-
.doc(
250-
new IndexRequest(CONNECTOR_INDEX_NAME).opType(DocWriteRequest.OpType.INDEX)
251-
.id(connectorId)
252-
.source(Map.of(Connector.IS_DELETED_FIELD.getPreferredName(), true))
253-
);
254-
clientWithOrigin.update(updateRequest, new DelegatingIndexNotFoundActionListener<>(connectorId, l, (ll, updateResponse) -> {
255-
if (updateResponse.getResult() == UpdateResponse.Result.NOT_FOUND) {
256-
ll.onFailure(new ResourceNotFoundException(connectorNotFoundErrorMsg(connectorId)));
257-
return;
258-
}
259-
if (shouldDeleteSyncJobs) {
260-
new ConnectorSyncJobIndexService(clientWithOrigin).deleteAllSyncJobsByConnectorId(
261-
connectorId,
262-
ll.map(r -> updateResponse)
252+
if (hardDelete) {
253+
final DeleteRequest deleteRequest = new DeleteRequest(CONNECTOR_INDEX_NAME).id(connectorId)
254+
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
255+
256+
clientWithOrigin.delete(
257+
deleteRequest,
258+
new DelegatingIndexNotFoundActionListener<>(connectorId, listener, (l, deleteResponse) -> {
259+
if (deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND) {
260+
l.onFailure(new ResourceNotFoundException(connectorNotFoundErrorMsg(connectorId)));
261+
return;
262+
}
263+
if (shouldDeleteSyncJobs) {
264+
new ConnectorSyncJobIndexService(clientWithOrigin).deleteAllSyncJobsByConnectorId(
265+
connectorId,
266+
l.map(r -> deleteResponse)
267+
);
268+
} else {
269+
l.onResponse(deleteResponse);
270+
}
271+
})
272+
);
273+
} else {
274+
getConnector(connectorId, false, listener.delegateFailure((l, connector) -> {
275+
final UpdateRequest updateRequest = new UpdateRequest(CONNECTOR_INDEX_NAME, connectorId).setRefreshPolicy(
276+
WriteRequest.RefreshPolicy.IMMEDIATE
277+
)
278+
.doc(
279+
new IndexRequest(CONNECTOR_INDEX_NAME).opType(DocWriteRequest.OpType.INDEX)
280+
.id(connectorId)
281+
.source(Map.of(Connector.IS_DELETED_FIELD.getPreferredName(), true))
263282
);
264-
} else {
265-
ll.onResponse(updateResponse);
266-
}
283+
clientWithOrigin.update(
284+
updateRequest,
285+
new DelegatingIndexNotFoundActionListener<>(connectorId, l, (ll, updateResponse) -> {
286+
if (updateResponse.getResult() == UpdateResponse.Result.NOT_FOUND) {
287+
ll.onFailure(new ResourceNotFoundException(connectorNotFoundErrorMsg(connectorId)));
288+
return;
289+
}
290+
if (shouldDeleteSyncJobs) {
291+
new ConnectorSyncJobIndexService(clientWithOrigin).deleteAllSyncJobsByConnectorId(
292+
connectorId,
293+
ll.map(r -> updateResponse)
294+
);
295+
} else {
296+
ll.onResponse(updateResponse);
297+
}
298+
})
299+
);
267300
}));
268-
}));
301+
}
269302
} catch (Exception e) {
270303
listener.onFailure(e);
271304
}

0 commit comments

Comments
 (0)