From 69f6687af9db6a0f0af82c9ed50cf2bdde7250b6 Mon Sep 17 00:00:00 2001 From: Shahzad <shahzad31comp@gmail.com> Date: Mon, 12 Aug 2024 21:13:33 +0200 Subject: [PATCH] [Synthetics] Delete monitor API via id param !! (#190210) ## Summary Allow deletion of monitor via id param !! User can now delete monitor via passing id as url param `DELETE <kibana host>:<port>/api/synthetics/monitors/<config_id>` Previous bulk delete via list of ids via API body still works as well !! Docs are updated !! --- .../monitors/delete-monitor-api.asciidoc | 24 +++++++++++-- .../management/monitor_list_table/columns.tsx | 2 +- .../routes/monitor_cruds/delete_monitor.ts | 36 ++++++++++++++----- .../apis/synthetics/delete_monitor.ts | 20 +++++++++++ .../synthetics_monitor_test_service.ts | 13 +++++++ 5 files changed, 83 insertions(+), 12 deletions(-) diff --git a/docs/api/synthetics/monitors/delete-monitor-api.asciidoc b/docs/api/synthetics/monitors/delete-monitor-api.asciidoc index 8730cc272a44..70861fcd60a3 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 <kibana host>:<port>/api/synthetics/monitors` +`DELETE <kibana host>:<port>/api/synthetics/monitors/<config_id>` -`DELETE <kibana host>:<port>/s/<space_id>/api/synthetics/monitors` +`DELETE <kibana host>:<port>/s/<space_id>/api/synthetics/monitors/<config_id>` === {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 <<kibana-feature-privileges,{kib} feature privileges>>. + +[[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 a2970af2e98c..1369fb086ada 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) => ( <NoPermissionsTooltip canEditSynthetics={canEditSynthetics} diff --git a/x-pack/plugins/observability_solution/synthetics/server/routes/monitor_cruds/delete_monitor.ts b/x-pack/plugins/observability_solution/synthetics/server/routes/monitor_cruds/delete_monitor.ts index df437cc43189..b7a1d0b2d48d 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/routes/monitor_cruds/delete_monitor.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/routes/monitor_cruds/delete_monitor.ts @@ -29,30 +29,48 @@ import { formatSecrets, normalizeSecrets } from '../../synthetics_service/utils/ export const deleteSyntheticsMonitorRoute: SyntheticsRestApiRouteFactory< DeleteParamsResponse[], - Record<string, any>, - Record<string, any>, + Record<string, string>, + Record<string, string>, { 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<any> => { 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 ed5e67c5fe26..c96175d2982b 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 4fc4c172eb6c..b30ea45a8c10 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; + } }