diff --git a/docs/api/synthetics/monitors/delete-monitor-api.asciidoc b/docs/api/synthetics/monitors/delete-monitor-api.asciidoc index 8730cc272a4460..70861fcd60a364 100644 --- a/docs/api/synthetics/monitors/delete-monitor-api.asciidoc +++ b/docs/api/synthetics/monitors/delete-monitor-api.asciidoc @@ -8,9 +8,9 @@ Deletes one or more monitors from the Synthetics app. === {api-request-title} -`DELETE :/api/synthetics/monitors` +`DELETE :/api/synthetics/monitors/` -`DELETE :/s//api/synthetics/monitors` +`DELETE :/s//api/synthetics/monitors/` === {api-prereq-title} @@ -20,6 +20,26 @@ You must have `all` privileges for the *Synthetics* feature in the *{observabili You must have `all` privileges for the *Synthetics* feature in the *{observability}* section of the <>. + +[[delete-monitor-api-path-params]] +=== {api-path-parms-title} + +`config_id`:: +(Required, string) The ID of the monitor that you want to delete. + + +Here is an example of a DELETE request to delete a monitor by ID: + +[source,sh] +-------------------------------------------------- +DELETE /api/synthetics/monitors/monitor1-id +-------------------------------------------------- + +==== Bulk Delete Monitors + +You can delete multiple monitors by sending a list of config ids to a DELETE request to the `/api/synthetics/monitors` endpoint. + + [[monitors-delete-request-body]] ==== Request Body diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/columns.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/columns.tsx index a2970af2e98c74..1369fb086adab6 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/columns.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/columns.tsx @@ -200,7 +200,7 @@ export function useMonitorListColumns({ }, { 'data-test-subj': 'syntheticsMonitorCopyAction', - isPrimary: true, + isPrimary: false, name: (fields) => ( , - Record, + Record, + Record, { ids: string[] } > = () => ({ method: 'DELETE', - path: SYNTHETICS_API_URLS.SYNTHETICS_MONITORS, + path: SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/{id?}', validate: {}, validation: { request: { - body: schema.object({ - ids: schema.arrayOf(schema.string(), { - minSize: 1, - }), + body: schema.nullable( + schema.object({ + ids: schema.arrayOf(schema.string(), { + minSize: 1, + }), + }) + ), + params: schema.object({ + id: schema.maybe(schema.string()), }), }, }, handler: async (routeContext): Promise => { const { request, response } = routeContext; - const { ids } = request.body; + const { ids } = request.body || {}; + const { id: queryId } = request.params; + + if (ids && queryId) { + return response.badRequest({ + body: { message: 'id must be provided either via param or body.' }, + }); + } const result: Array<{ id: string; deleted: boolean; error?: string }> = []; + const idsToDelete = [...(ids ?? []), ...(queryId ? [queryId] : [])]; + if (idsToDelete.length === 0) { + return response.badRequest({ + body: { message: 'id must be provided via param or body.' }, + }); + } - await pMap(ids, async (id) => { + await pMap(idsToDelete, async (id) => { try { const { errors, res } = await deleteMonitor({ routeContext, diff --git a/x-pack/test/api_integration/apis/synthetics/delete_monitor.ts b/x-pack/test/api_integration/apis/synthetics/delete_monitor.ts index ed5e67c5fe261e..c96175d2982b3b 100644 --- a/x-pack/test/api_integration/apis/synthetics/delete_monitor.ts +++ b/x-pack/test/api_integration/apis/synthetics/delete_monitor.ts @@ -79,6 +79,26 @@ export default function ({ getService }: FtrProviderContext) { // Hit get endpoint and expect 404 as well await supertest.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitorId).expect(404); }); + + it('deletes monitor by param id', async () => { + const { id: monitorId } = await saveMonitor(httpMonitorJson as MonitorFields); + + const deleteResponse = await monitorTestService.deleteMonitorByIdParam(monitorId, 200); + + expect(deleteResponse.body).eql([{ id: monitorId, deleted: true }]); + + // Hit get endpoint and expect 404 as well + await supertest.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitorId).expect(404); + }); + + it('throws error if both body and param are missing', async () => { + const deleteResponse = await supertest + .delete(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS) + .send() + .set('kbn-xsrf', 'true'); + expect(deleteResponse.status).to.eql(400); + }); + it('deletes multiple monitors by id', async () => { const { id: monitorId } = await saveMonitor(httpMonitorJson as MonitorFields); const { id: monitorId2 } = await saveMonitor({ diff --git a/x-pack/test/api_integration/apis/synthetics/services/synthetics_monitor_test_service.ts b/x-pack/test/api_integration/apis/synthetics/services/synthetics_monitor_test_service.ts index 4fc4c172eb6c5a..b30ea45a8c10e1 100644 --- a/x-pack/test/api_integration/apis/synthetics/services/synthetics_monitor_test_service.ts +++ b/x-pack/test/api_integration/apis/synthetics/services/synthetics_monitor_test_service.ts @@ -173,4 +173,17 @@ export class SyntheticsMonitorTestService { expect(deleteResponse.status).to.eql(statusCode); return deleteResponse; } + + async deleteMonitorByIdParam(monitorId?: string, statusCode = 200, spaceId?: string) { + const deleteResponse = await this.supertest + .delete( + spaceId + ? `/s/${spaceId}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}/${monitorId}` + : SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitorId + ) + .send() + .set('kbn-xsrf', 'true'); + expect(deleteResponse.status).to.eql(statusCode); + return deleteResponse; + } }