From a0f8dff6e1937d643fe1c2cec1a7cbd7c37f93c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Tue, 31 Jan 2023 16:15:16 +0100 Subject: [PATCH 1/9] Refactor code to determine the service URL --- .../service_api_client.test.ts | 49 +++++++++++++++++-- .../synthetics_service/service_api_client.ts | 25 +++++++--- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts index 62a54db4460a6..8811d6c53635c 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts @@ -154,7 +154,6 @@ describe('callAPI', () => { 1, { isEdit: undefined, - runOnce: undefined, monitors: testMonitors.filter((monitor: any) => monitor.locations.some((loc: any) => loc.id === 'us_central') ), @@ -168,7 +167,6 @@ describe('callAPI', () => { 2, { isEdit: undefined, - runOnce: undefined, monitors: testMonitors.filter((monitor: any) => monitor.locations.some((loc: any) => loc.id === 'us_central_qa') ), @@ -182,7 +180,6 @@ describe('callAPI', () => { 3, { isEdit: undefined, - runOnce: undefined, monitors: testMonitors.filter((monitor: any) => monitor.locations.some((loc: any) => loc.id === 'us_central_staging') ), @@ -275,7 +272,6 @@ describe('callAPI', () => { stackVersion: '8.7.0', } as UptimeServerSetup ); - apiClient.locations = testLocations; const output = { hosts: ['https://localhost:9200'], api_key: '12345' }; @@ -302,6 +298,51 @@ describe('callAPI', () => { url: 'https://service.dev/monitors', }); }); + + it('Calls the `/run` endpoint when calling `runOnce`', async () => { + const axiosSpy = (axios as jest.MockedFunction).mockResolvedValue({ + status: 200, + statusText: 'ok', + headers: {}, + config: {}, + data: { allowed: true, signupUrl: 'http://localhost:666/example' }, + }); + + const apiClient = new ServiceAPIClient( + logger, + { + manifestUrl: 'http://localhost:8080/api/manifest', + tls: { certificate: 'test-certificate', key: 'test-key' } as any, + }, + { isDev: true, stackVersion: '8.7.0' } as UptimeServerSetup + ); + + apiClient.locations = testLocations; + + const output = { hosts: ['https://localhost:9200'], api_key: '12345' }; + + await apiClient.runOnce({ + monitors: testMonitors, + output, + }); + + expect(axiosSpy).toHaveBeenNthCalledWith(1, { + data: { monitors: request1, is_edit: undefined, output, stack_version: '8.7.0' }, + headers: { + 'x-kibana-version': '8.7.0', + }, + httpsAgent: expect.objectContaining({ + options: { + rejectUnauthorized: true, + path: null, + cert: 'test-certificate', + key: 'test-key', + }, + }), + method: 'POST', + url: 'https://service.dev/run', + }); + }); }); const testLocations: PublicLocations = [ diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts index 0f902ff52a8d7..7daa0a4e716d8 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts @@ -25,7 +25,7 @@ export interface ServiceData { hosts: string[]; api_key: string; }; - runOnce?: boolean; + endpoint?: 'monitors' | 'run' | 'sync'; isEdit?: boolean; } @@ -92,7 +92,7 @@ export class ServiceAPIClient { } async runOnce(data: ServiceData) { - return this.callAPI('POST', { ...data, runOnce: true }); + return this.callAPI('POST', { ...data, endpoint: 'run' }); } addVersionHeader(req: AxiosRequestConfig) { @@ -137,7 +137,7 @@ export class ServiceAPIClient { async callAPI( method: 'POST' | 'PUT' | 'DELETE', - { monitors: allMonitors, output, runOnce, isEdit }: ServiceData + { monitors: allMonitors, output, isEdit, endpoint }: ServiceData ) { if (this.username === TEST_SERVICE_USERNAME) { // we don't want to call service while local integration tests are running @@ -156,7 +156,7 @@ export class ServiceAPIClient { promises.push( rxjsFrom( this.callServiceEndpoint( - { monitors: locMonitors, isEdit, runOnce, output }, + { monitors: locMonitors, isEdit, output, endpoint }, method, url ) @@ -196,19 +196,28 @@ export class ServiceAPIClient { } async callServiceEndpoint( - { monitors, output, runOnce, isEdit }: ServiceData, + { monitors, output, endpoint = 'monitors', isEdit }: ServiceData, method: 'POST' | 'PUT' | 'DELETE', - url: string + baseUrl: string ) { // don't need to pass locations to heartbeat const monitorsStreams = monitors.map(({ locations, ...rest }) => convertToDataStreamFormat(rest) ); + let url = baseUrl; + switch (endpoint) { + case 'monitors': + url += '/monitors'; + break; + case 'run': + url += '/run'; + } + return axios( this.addVersionHeader({ method, - url: url + (runOnce ? '/run' : '/monitors'), + url, data: { monitors: monitorsStreams, output, @@ -220,7 +229,7 @@ export class ServiceAPIClient { Authorization: this.authorization, } : undefined, - httpsAgent: this.getHttpsAgent(url), + httpsAgent: this.getHttpsAgent(baseUrl), }) ); } From 9c1a39adcd0ac31405ae92ebd17a1923410840d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Tue, 31 Jan 2023 16:31:49 +0100 Subject: [PATCH 2/9] Add `/monitors/sync` endpoint --- .../service_api_client.test.ts | 45 +++++++++++++++++++ .../synthetics_service/service_api_client.ts | 8 ++++ 2 files changed, 53 insertions(+) diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts index 8811d6c53635c..14523d33d237c 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts @@ -343,6 +343,51 @@ describe('callAPI', () => { url: 'https://service.dev/run', }); }); + + it('Calls the `/monitors/sync` endpoint when calling `syncMonitors`', async () => { + const axiosSpy = (axios as jest.MockedFunction).mockResolvedValue({ + status: 200, + statusText: 'ok', + headers: {}, + config: {}, + data: { allowed: true, signupUrl: 'http://localhost:666/example' }, + }); + + const apiClient = new ServiceAPIClient( + logger, + { + manifestUrl: 'http://localhost:8080/api/manifest', + tls: { certificate: 'test-certificate', key: 'test-key' } as any, + }, + { isDev: true, stackVersion: '8.7.0' } as UptimeServerSetup + ); + + apiClient.locations = testLocations; + + const output = { hosts: ['https://localhost:9200'], api_key: '12345' }; + + await apiClient.syncMonitors({ + monitors: testMonitors, + output, + }); + + expect(axiosSpy).toHaveBeenNthCalledWith(1, { + data: { monitors: request1, is_edit: undefined, output, stack_version: '8.7.0' }, + headers: { + 'x-kibana-version': '8.7.0', + }, + httpsAgent: expect.objectContaining({ + options: { + rejectUnauthorized: true, + path: null, + cert: 'test-certificate', + key: 'test-key', + }, + }), + method: 'PUT', + url: 'https://service.dev/monitors/sync', + }); + }); }); const testLocations: PublicLocations = [ diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts index 7daa0a4e716d8..e4e0e2d9a2173 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts @@ -95,6 +95,10 @@ export class ServiceAPIClient { return this.callAPI('POST', { ...data, endpoint: 'run' }); } + async syncMonitors(data: ServiceData) { + return this.callAPI('PUT', { ...data, endpoint: 'sync' }); + } + addVersionHeader(req: AxiosRequestConfig) { req.headers = { ...req.headers, 'x-kibana-version': this.stackVersion }; return req; @@ -212,6 +216,10 @@ export class ServiceAPIClient { break; case 'run': url += '/run'; + break; + case 'sync': + url += '/monitors/sync'; + break; } return axios( From 7e13b0c80c5fb7cad24132c08f5a6dbbfa13a8f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Tue, 31 Jan 2023 16:50:25 +0100 Subject: [PATCH 3/9] Add endpoint path to the error messages --- .../synthetics/server/synthetics_service/service_api_client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts index e4e0e2d9a2173..35254ed183056 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts @@ -175,7 +175,7 @@ export class ServiceAPIClient { pushErrors.push({ locationId: id, error: err.response?.data! }); const reason = err.response?.data?.reason ?? ''; - err.message = `Failed to call service location ${url} with method ${method} with ${locMonitors.length} monitors: ${err.message}, ${reason}`; + err.message = `Failed to call service location ${url}${err.request?.path} with method ${method} with ${locMonitors.length} monitors: ${err.message}, ${reason}`; this.logger.error(err); sendErrorTelemetryEvents(this.logger, this.server.telemetry, { reason: err.response?.data?.reason, From ba848cbee77b164de99e33dff0fd042b12d0f26f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Tue, 31 Jan 2023 16:50:37 +0100 Subject: [PATCH 4/9] Use the new endpoint to sync the monitors --- .../synthetics/server/synthetics_service/synthetics_service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts index 7e7b304f5edaa..d9453a6fba3a6 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts @@ -318,7 +318,7 @@ export class SyntheticsService { this.logger.debug(`${monitors.length} monitors will be pushed to synthetics service.`); - service.syncErrors = await this.apiClient.put({ + service.syncErrors = await this.apiClient.syncMonitors({ monitors, output, }); From e17bd890ef8c2a575ab2b982e2f59c6fc3705d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Thu, 2 Feb 2023 13:32:01 +0100 Subject: [PATCH 5/9] POST means POST --- .../synthetics/server/synthetics_service/service_api_client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts index 35254ed183056..b61126c7f7605 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts @@ -80,7 +80,7 @@ export class ServiceAPIClient { } async post(data: ServiceData) { - return this.callAPI('PUT', data); + return this.callAPI('POST', data); } async put(data: ServiceData) { From a6f066651551480b6ecdd7520c1d9ac835fb0096 Mon Sep 17 00:00:00 2001 From: shahzad31 Date: Mon, 17 Apr 2023 14:50:47 +0200 Subject: [PATCH 6/9] fix lint --- .../synthetics/server/synthetics_service/service_api_client.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts index 2d199098362c2..600ea0fbea223 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts @@ -161,8 +161,7 @@ export class ServiceAPIClient { promises.push( rxjsFrom( this.callServiceEndpoint( - { monitors: locMonitors, isEdit, runOnce, output, licenseLevel }, - { monitors: locMonitors, isEdit, output, endpoint }, + { monitors: locMonitors, isEdit, endpoint, output, licenseLevel }, method, url ) From 898213d8b335ad3dac1b50c1330e8887e1f5ce20 Mon Sep 17 00:00:00 2001 From: shahzad31 Date: Mon, 17 Apr 2023 15:37:24 +0200 Subject: [PATCH 7/9] update endpoints --- .../getting_started/getting_started_page.tsx | 4 +++ .../service_api_client.test.ts | 18 ++++++++++-- .../synthetics_service/service_api_client.ts | 29 +++++++++---------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.tsx index c63faf20904a4..f42b781089aea 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.tsx @@ -29,6 +29,7 @@ import { setAddingNewPrivateLocation, getAgentPoliciesAction, selectAgentPolicies, + cleanMonitorListState, } from '../../state'; import { MONITOR_ADD_ROUTE } from '../../../../../common/constants/ui'; import { PrivateLocation } from '../../../../../common/runtime_types'; @@ -46,6 +47,9 @@ export const GettingStartedPage = () => { if (canReadAgentPolicies) { dispatch(getAgentPoliciesAction.get()); } + return () => { + dispatch(cleanMonitorListState()); + }; }, [canReadAgentPolicies, dispatch]); useBreadcrumbs([{ text: MONITORING_OVERVIEW_LABEL }]); // No extra breadcrumbs on overview diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts index 68a2879dd7c59..56ab66e0d1c8d 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts @@ -376,10 +376,17 @@ describe('callAPI', () => { await apiClient.runOnce({ monitors: testMonitors, output, + licenseLevel: 'trial', }); expect(axiosSpy).toHaveBeenNthCalledWith(1, { - data: { monitors: request1, is_edit: undefined, output, stack_version: '8.7.0' }, + data: { + monitors: request1, + is_edit: undefined, + output, + stack_version: '8.7.0', + license_level: 'trial', + }, headers: { 'x-kibana-version': '8.7.0', }, @@ -421,10 +428,17 @@ describe('callAPI', () => { await apiClient.syncMonitors({ monitors: testMonitors, output, + licenseLevel: 'trial', }); expect(axiosSpy).toHaveBeenNthCalledWith(1, { - data: { monitors: request1, is_edit: undefined, output, stack_version: '8.7.0' }, + data: { + monitors: request1, + is_edit: undefined, + output, + stack_version: '8.7.0', + license_level: 'trial', + }, headers: { 'x-kibana-version': '8.7.0', }, diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts index 600ea0fbea223..2ce45fbd842e2 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts @@ -25,7 +25,7 @@ export interface ServiceData { hosts: string[]; api_key: string; }; - endpoint?: 'monitors' | 'run' | 'sync'; + endpoint?: 'monitors' | 'runOnce' | 'sync'; isEdit?: boolean; licenseLevel: string; } @@ -93,7 +93,7 @@ export class ServiceAPIClient { } async runOnce(data: ServiceData) { - return this.callAPI('POST', { ...data, endpoint: 'run' }); + return this.callAPI('POST', { ...data, endpoint: 'runOnce' }); } async syncMonitors(data: ServiceData) { @@ -158,18 +158,17 @@ export class ServiceAPIClient { locations?.find((loc) => loc.id === id && loc.isServiceManaged) ); if (locMonitors.length > 0) { + const promise = this.callServiceEndpoint( + { monitors: locMonitors, isEdit, endpoint, output, licenseLevel }, + method, + url + ); promises.push( - rxjsFrom( - this.callServiceEndpoint( - { monitors: locMonitors, isEdit, endpoint, output, licenseLevel }, - method, - url - ) - ).pipe( + rxjsFrom(promise).pipe( tap((result) => { this.logger.debug(result.data); this.logger.debug( - `Successfully called service location ${url} with method ${method} with ${locMonitors.length} monitors ` + `Successfully called service location ${url}${result.request.path} for ${endpoint} with method ${method} with ${locMonitors.length} monitors ` ); }), catchError((err: AxiosError<{ reason: string; status: number }>) => { @@ -215,7 +214,7 @@ export class ServiceAPIClient { case 'monitors': url += '/monitors'; break; - case 'run': + case 'runOnce': url += '/run'; break; case 'sync': @@ -223,6 +222,8 @@ export class ServiceAPIClient { break; } + const authHeader = this.authorization ? { Authorization: this.authorization } : undefined; + return axios( this.addVersionHeader({ method, @@ -234,11 +235,7 @@ export class ServiceAPIClient { is_edit: isEdit, license_level: licenseLevel, }, - headers: this.authorization - ? { - Authorization: this.authorization, - } - : undefined, + headers: authHeader, httpsAgent: this.getHttpsAgent(baseUrl), }) ); From f486a20a17180f5de479b493861c87d07eda0e3f Mon Sep 17 00:00:00 2001 From: shahzad31 Date: Mon, 17 Apr 2023 15:46:54 +0200 Subject: [PATCH 8/9] update endpoints --- .../synthetics/server/synthetics_service/service_api_client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts index 2ce45fbd842e2..32de183be0161 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts @@ -168,7 +168,7 @@ export class ServiceAPIClient { tap((result) => { this.logger.debug(result.data); this.logger.debug( - `Successfully called service location ${url}${result.request.path} for ${endpoint} with method ${method} with ${locMonitors.length} monitors ` + `Successfully called service location ${url}${result.request.path} with method ${method} with ${locMonitors.length} monitors ` ); }), catchError((err: AxiosError<{ reason: string; status: number }>) => { From 92e3c86ff01cf8e63072fb3e9caae2825e78b620 Mon Sep 17 00:00:00 2001 From: shahzad31 Date: Tue, 18 Apr 2023 10:37:56 +0200 Subject: [PATCH 9/9] update test --- .../server/synthetics_service/service_api_client.test.ts | 6 +++--- .../server/synthetics_service/service_api_client.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts index 56ab66e0d1c8d..22ec8e8a3213e 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts @@ -281,15 +281,15 @@ describe('callAPI', () => { }); expect(logger.debug).toHaveBeenNthCalledWith( 2, - 'Successfully called service location https://service.dev with method POST with 4 monitors ' + 'Successfully called service location https://service.devundefined with method POST with 4 monitors' ); expect(logger.debug).toHaveBeenNthCalledWith( 4, - 'Successfully called service location https://qa.service.elstc.co with method POST with 4 monitors ' + 'Successfully called service location https://qa.service.elstc.coundefined with method POST with 4 monitors' ); expect(logger.debug).toHaveBeenNthCalledWith( 6, - 'Successfully called service location https://qa.service.stg.co with method POST with 1 monitors ' + 'Successfully called service location https://qa.service.stg.coundefined with method POST with 1 monitors' ); }); diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts index 32de183be0161..bfc872f3680a8 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.ts @@ -168,7 +168,7 @@ export class ServiceAPIClient { tap((result) => { this.logger.debug(result.data); this.logger.debug( - `Successfully called service location ${url}${result.request.path} with method ${method} with ${locMonitors.length} monitors ` + `Successfully called service location ${url}${result.request?.path} with method ${method} with ${locMonitors.length} monitors` ); }), catchError((err: AxiosError<{ reason: string; status: number }>) => {