diff --git a/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap index ab38ee9adc6c2b..6fcce75cea70e5 100644 --- a/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap @@ -1823,9 +1823,7 @@ exports[`EmptyState component renders error message when an error occurs 1`] = `
-

+

There was an error fetching your data.

diff --git a/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/empty_state.test.tsx b/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/empty_state.test.tsx index 6328789d03f29f..0de5cd3ab31be5 100644 --- a/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/empty_state.test.tsx +++ b/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/empty_state.test.tsx @@ -42,7 +42,9 @@ describe('EmptyState component', () => { it(`renders error message when an error occurs`, () => { const errors: IHttpFetchError[] = [ - new HttpFetchError('There was an error fetching your data.', 'error', {} as any), + new HttpFetchError('There was an error fetching your data.', 'error', {} as any, {} as any, { + body: { message: 'There was an error fetching your data.' }, + }), ]; const component = mountWithRouter( diff --git a/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state_error.tsx b/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state_error.tsx index f7b77df8497f95..165b123d8884db 100644 --- a/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state_error.tsx +++ b/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state_error.tsx @@ -15,7 +15,7 @@ interface EmptyStateErrorProps { export const EmptyStateError = ({ errors }: EmptyStateErrorProps) => { const unauthorized = errors.find( - (error: Error) => error.message && error.message.includes('unauthorized') + (error: IHttpFetchError) => error.message && error.message.includes('unauthorized') ); return ( @@ -46,7 +46,9 @@ export const EmptyStateError = ({ errors }: EmptyStateErrorProps) => { body={ {!unauthorized && - errors.map((error: Error) =>

{error.message}

)} + errors.map((error: IHttpFetchError) => ( +

{error.body.message || error.message}

+ ))}
} /> diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_list.test.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_list.test.tsx index 1d8a7a771e0c51..352369cfdb72b8 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_list.test.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_list.test.tsx @@ -17,6 +17,7 @@ import { MonitorListComponent, noItemsMessage } from '../monitor_list'; import { renderWithRouter, shallowWithRouter } from '../../../../lib'; import * as redux from 'react-redux'; import moment from 'moment'; +import { IHttpFetchError } from '../../../../../../../../src/core/public'; jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => { return { @@ -187,7 +188,11 @@ describe('MonitorList component', () => { it('renders error list', () => { const component = shallowWithRouter( diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx index 5e0cc5d3dee1d4..f31e25484a9361 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx @@ -187,7 +187,7 @@ export const MonitorListComponent: ({ ( { @@ -41,7 +42,7 @@ export const monitorListReducer = handleActions( error: undefined, list: { ...action.payload }, }), - [String(getMonitorListFailure)]: (state: MonitorList, action: Action) => ({ + [String(getMonitorListFailure)]: (state: MonitorList, action: Action) => ({ ...state, error: action.payload, loading: false, diff --git a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts index b75c729c2104a2..cd98ba1600d34b 100644 --- a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts @@ -9,17 +9,20 @@ import { IRouter, SavedObjectsClientContract, ISavedObjectsRepository, - ILegacyScopedClusterClient, + IScopedClusterClient, + ElasticsearchClient, } from 'src/core/server'; import { UMKibanaRoute } from '../../../rest_api'; import { PluginSetupContract } from '../../../../../features/server'; import { DynamicSettings } from '../../../../common/runtime_types'; import { MlPluginSetup as MlSetup } from '../../../../../ml/server'; -export type ESAPICaller = ILegacyScopedClusterClient['callAsCurrentUser']; - export type UMElasticsearchQueryFn = ( - params: { callES: ESAPICaller; dynamicSettings: DynamicSettings } & P + params: { + callES: ElasticsearchClient; + esClient?: IScopedClusterClient; + dynamicSettings: DynamicSettings; + } & P ) => Promise; export type UMSavedObjectsQueryFn = ( diff --git a/x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts b/x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts index a8969f2621f292..2126b484b1cfd3 100644 --- a/x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts +++ b/x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts @@ -5,10 +5,14 @@ */ import moment from 'moment'; -import { ISavedObjectsRepository, SavedObjectsClientContract } from 'kibana/server'; +import { + ISavedObjectsRepository, + ILegacyScopedClusterClient, + SavedObjectsClientContract, + ElasticsearchClient, +} from 'kibana/server'; import { CollectorFetchContext, UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { PageViewParams, UptimeTelemetry, Usage } from './types'; -import { ESAPICaller } from '../framework'; import { savedObjectsAdapter } from '../../saved_objects'; interface UptimeTelemetryCollector { @@ -21,6 +25,8 @@ const BUCKET_SIZE = 3600; const BUCKET_NUMBER = 24; export class KibanaTelemetryAdapter { + public static callCluster: ILegacyScopedClusterClient['callAsCurrentUser'] | ElasticsearchClient; + public static registerUsageCollector = ( usageCollector: UsageCollectionSetup, getSavedObjectsClient: () => ISavedObjectsRepository | undefined @@ -125,7 +131,7 @@ export class KibanaTelemetryAdapter { } public static async countNoOfUniqueMonitorAndLocations( - callCluster: ESAPICaller, + callCluster: ILegacyScopedClusterClient['callAsCurrentUser'] | ElasticsearchClient, savedObjectsClient: ISavedObjectsRepository | SavedObjectsClientContract ) { const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings(savedObjectsClient); @@ -187,7 +193,11 @@ export class KibanaTelemetryAdapter { }, }; - const result = await callCluster('search', params); + const { body: result } = + typeof callCluster === 'function' + ? await callCluster('search', params) + : await callCluster.search(params); + const numberOfUniqueMonitors: number = result?.aggregations?.unique_monitors?.value ?? 0; const numberOfUniqueLocations: number = result?.aggregations?.unique_locations?.value ?? 0; const monitorNameStats: any = result?.aggregations?.monitor_name; diff --git a/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts b/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts index 06b298aedeb2b5..ccb1e5a40ad2de 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts @@ -56,6 +56,8 @@ const mockOptions = ( services = alertsMock.createAlertServices(), state = {} ): any => { + services.scopedClusterClient = jest.fn() as any; + services.savedObjectsClient.get.mockResolvedValue({ id: '', type: '', @@ -282,7 +284,8 @@ describe('status check alert', () => { expect.assertions(5); toISOStringSpy.mockImplementation(() => 'foo date string'); const mockGetter: jest.Mock = jest.fn(); - mockGetter.mockReturnValue([ + + mockGetter.mockReturnValueOnce([ { monitorId: 'first', location: 'harrisburg', @@ -326,6 +329,7 @@ describe('status check alert', () => { const state = await alert.executor(options); const [{ value: alertInstanceMock }] = alertServices.alertInstanceFactory.mock.results; expect(mockGetter).toHaveBeenCalledTimes(1); + expect(mockGetter.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { diff --git a/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts b/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts index 9dddc0035f6902..d4c26fe83b5fc1 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts @@ -12,12 +12,12 @@ import { ACTION_GROUP_DEFINITIONS } from '../../../common/constants/alerts'; import { commonStateTranslations, durationAnomalyTranslations } from './translations'; import { AnomaliesTableRecord } from '../../../../ml/common/types/anomalies'; import { getSeverityType } from '../../../../ml/common/util/anomaly_utils'; -import { savedObjectsAdapter } from '../saved_objects'; import { UptimeCorePlugins } from '../adapters/framework'; import { UptimeAlertTypeFactory } from './types'; import { Ping } from '../../../common/runtime_types/ping'; import { getMLJobId } from '../../../common/lib'; import { getLatestMonitor } from '../requests/get_latest_monitor'; +import { uptimeAlertWrapper } from './uptime_alert_wrapper'; const { DURATION_ANOMALY } = ACTION_GROUP_DEFINITIONS; @@ -61,61 +61,58 @@ const getAnomalies = async ( ); }; -export const durationAnomalyAlertFactory: UptimeAlertTypeFactory = (_server, _libs, plugins) => ({ - id: 'xpack.uptime.alerts.durationAnomaly', - name: durationAnomalyTranslations.alertFactoryName, - validate: { - params: schema.object({ - monitorId: schema.string(), - severity: schema.number(), - }), - }, - defaultActionGroupId: DURATION_ANOMALY.id, - actionGroups: [ - { - id: DURATION_ANOMALY.id, - name: DURATION_ANOMALY.name, +export const durationAnomalyAlertFactory: UptimeAlertTypeFactory = (_server, _libs, plugins) => + uptimeAlertWrapper({ + id: 'xpack.uptime.alerts.durationAnomaly', + name: durationAnomalyTranslations.alertFactoryName, + validate: { + params: schema.object({ + monitorId: schema.string(), + severity: schema.number(), + }), }, - ], - actionVariables: { - context: [], - state: [...durationAnomalyTranslations.actionVariables, ...commonStateTranslations], - }, - producer: 'uptime', - async executor(options) { - const { - services: { alertInstanceFactory, callCluster, savedObjectsClient }, - state, - params, - } = options; + defaultActionGroupId: DURATION_ANOMALY.id, + actionGroups: [ + { + id: DURATION_ANOMALY.id, + name: DURATION_ANOMALY.name, + }, + ], + actionVariables: { + context: [], + state: [...durationAnomalyTranslations.actionVariables, ...commonStateTranslations], + }, + async executor({ options, esClient, savedObjectsClient, dynamicSettings }) { + const { + services: { alertInstanceFactory }, + state, + params, + } = options; - const { anomalies } = - (await getAnomalies(plugins, savedObjectsClient, params, state.lastCheckedAt)) ?? {}; + const { anomalies } = + (await getAnomalies(plugins, savedObjectsClient, params, state.lastCheckedAt)) ?? {}; - const foundAnomalies = anomalies?.length > 0; + const foundAnomalies = anomalies?.length > 0; - if (foundAnomalies) { - const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings( - savedObjectsClient - ); - const monitorInfo = await getLatestMonitor({ - dynamicSettings, - callES: callCluster, - dateStart: 'now-15m', - dateEnd: 'now', - monitorId: params.monitorId, - }); - anomalies.forEach((anomaly, index) => { - const alertInstance = alertInstanceFactory(DURATION_ANOMALY.id + index); - const summary = getAnomalySummary(anomaly, monitorInfo); - alertInstance.replaceState({ - ...updateState(state, false), - ...summary, + if (foundAnomalies) { + const monitorInfo = await getLatestMonitor({ + dynamicSettings, + callES: esClient, + dateStart: 'now-15m', + dateEnd: 'now', + monitorId: params.monitorId, + }); + anomalies.forEach((anomaly, index) => { + const alertInstance = alertInstanceFactory(DURATION_ANOMALY.id + index); + const summary = getAnomalySummary(anomaly, monitorInfo); + alertInstance.replaceState({ + ...updateState(state, false), + ...summary, + }); + alertInstance.scheduleActions(DURATION_ANOMALY.id); }); - alertInstance.scheduleActions(DURATION_ANOMALY.id); - }); - } + } - return updateState(state, foundAnomalies); - }, -}); + return updateState(state, foundAnomalies); + }, + }); diff --git a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts index 7feb916046e3a0..b1b3666b40dc6b 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts @@ -26,7 +26,6 @@ import { GetMonitorStatusResult } from '../requests/get_monitor_status'; import { UNNAMED_LOCATION } from '../../../common/constants'; import { uptimeAlertWrapper } from './uptime_alert_wrapper'; import { MonitorStatusTranslations } from '../../../common/translations'; -import { ESAPICaller } from '../adapters/framework'; import { getUptimeIndexPattern, IndexPatternTitleAndFields } from '../requests/get_index_pattern'; import { UMServerLibs } from '../lib'; @@ -81,7 +80,6 @@ export const generateFilterDSL = async ( export const formatFilterString = async ( dynamicSettings: DynamicSettings, - callES: ESAPICaller, esClient: ElasticsearchClient, filters: StatusCheckFilters, search: string, @@ -90,9 +88,8 @@ export const formatFilterString = async ( await generateFilterDSL( () => libs?.requests?.getIndexPattern - ? libs?.requests?.getIndexPattern({ callES, esClient, dynamicSettings }) + ? libs?.requests?.getIndexPattern({ esClient, dynamicSettings }) : getUptimeIndexPattern({ - callES, esClient, dynamicSettings, }), @@ -237,12 +234,15 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) = ], state: [...commonMonitorStateI18, ...commonStateTranslations], }, - async executor( - { params: rawParams, state, services: { alertInstanceFactory } }, - callES, + async executor({ + options: { + params: rawParams, + state, + services: { alertInstanceFactory }, + }, esClient, - dynamicSettings - ) { + dynamicSettings, + }) { const { filters, search, @@ -258,7 +258,6 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) = const filterString = await formatFilterString( dynamicSettings, - callES, esClient, filters, search, @@ -278,7 +277,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) = // after that shouldCheckStatus should be explicitly false if (!(!oldVersionTimeRange && shouldCheckStatus === false)) { downMonitorsByLocation = await libs.requests.getMonitorStatus({ - callES, + callES: esClient, dynamicSettings, timerange, numTimes, @@ -311,7 +310,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) = let availabilityResults: GetMonitorAvailabilityResult[] = []; if (shouldCheckAvailability) { availabilityResults = await libs.requests.getMonitorAvailability({ - callES, + callES: esClient, dynamicSettings, ...availability, filters: JSON.stringify(filterString) || undefined, diff --git a/x-pack/plugins/uptime/server/lib/alerts/tls.ts b/x-pack/plugins/uptime/server/lib/alerts/tls.ts index d4853ad7a9cb03..11f602d10bf51c 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/tls.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/tls.ts @@ -7,13 +7,13 @@ import moment from 'moment'; import { schema } from '@kbn/config-schema'; import { UptimeAlertTypeFactory } from './types'; -import { savedObjectsAdapter } from '../saved_objects'; import { updateState } from './common'; import { ACTION_GROUP_DEFINITIONS } from '../../../common/constants/alerts'; import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../common/constants'; import { Cert, CertResult } from '../../../common/runtime_types'; import { commonStateTranslations, tlsTranslations } from './translations'; import { DEFAULT_FROM, DEFAULT_TO } from '../../rest_api/certs/certs'; +import { uptimeAlertWrapper } from './uptime_alert_wrapper'; const { TLS } = ACTION_GROUP_DEFINITIONS; @@ -82,74 +82,73 @@ export const getCertSummary = ( }; }; -export const tlsAlertFactory: UptimeAlertTypeFactory = (_server, libs) => ({ - id: 'xpack.uptime.alerts.tls', - name: tlsTranslations.alertFactoryName, - validate: { - params: schema.object({}), - }, - defaultActionGroupId: TLS.id, - actionGroups: [ - { - id: TLS.id, - name: TLS.name, +export const tlsAlertFactory: UptimeAlertTypeFactory = (_server, libs) => + uptimeAlertWrapper({ + id: 'xpack.uptime.alerts.tls', + name: tlsTranslations.alertFactoryName, + validate: { + params: schema.object({}), }, - ], - actionVariables: { - context: [], - state: [...tlsTranslations.actionVariables, ...commonStateTranslations], - }, - producer: 'uptime', - async executor(options) { - const { - services: { alertInstanceFactory, callCluster, savedObjectsClient }, - state, - } = options; - const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings(savedObjectsClient); - - const { certs, total }: CertResult = await libs.requests.getCerts({ - callES: callCluster, - dynamicSettings, - from: DEFAULT_FROM, - to: DEFAULT_TO, - index: 0, - size: DEFAULT_SIZE, - notValidAfter: `now+${ - dynamicSettings?.certExpirationThreshold ?? - DYNAMIC_SETTINGS_DEFAULTS.certExpirationThreshold - }d`, - notValidBefore: `now-${ - dynamicSettings?.certAgeThreshold ?? DYNAMIC_SETTINGS_DEFAULTS.certAgeThreshold - }d`, - sortBy: 'common_name', - direction: 'desc', - }); - - const foundCerts = total > 0; - - if (foundCerts) { - const absoluteExpirationThreshold = moment() - .add( - dynamicSettings.certExpirationThreshold ?? - DYNAMIC_SETTINGS_DEFAULTS.certExpirationThreshold, - 'd' - ) - .valueOf(); - const absoluteAgeThreshold = moment() - .subtract( - dynamicSettings.certAgeThreshold ?? DYNAMIC_SETTINGS_DEFAULTS.certAgeThreshold, - 'd' - ) - .valueOf(); - const alertInstance = alertInstanceFactory(TLS.id); - const summary = getCertSummary(certs, absoluteExpirationThreshold, absoluteAgeThreshold); - alertInstance.replaceState({ - ...updateState(state, foundCerts), - ...summary, + defaultActionGroupId: TLS.id, + actionGroups: [ + { + id: TLS.id, + name: TLS.name, + }, + ], + actionVariables: { + context: [], + state: [...tlsTranslations.actionVariables, ...commonStateTranslations], + }, + async executor({ options, dynamicSettings, esClient }) { + const { + services: { alertInstanceFactory }, + state, + } = options; + + const { certs, total }: CertResult = await libs.requests.getCerts({ + callES: esClient, + dynamicSettings, + from: DEFAULT_FROM, + to: DEFAULT_TO, + index: 0, + size: DEFAULT_SIZE, + notValidAfter: `now+${ + dynamicSettings?.certExpirationThreshold ?? + DYNAMIC_SETTINGS_DEFAULTS.certExpirationThreshold + }d`, + notValidBefore: `now-${ + dynamicSettings?.certAgeThreshold ?? DYNAMIC_SETTINGS_DEFAULTS.certAgeThreshold + }d`, + sortBy: 'common_name', + direction: 'desc', }); - alertInstance.scheduleActions(TLS.id); - } - return updateState(state, foundCerts); - }, -}); + const foundCerts = total > 0; + + if (foundCerts) { + const absoluteExpirationThreshold = moment() + .add( + dynamicSettings.certExpirationThreshold ?? + DYNAMIC_SETTINGS_DEFAULTS.certExpirationThreshold, + 'd' + ) + .valueOf(); + const absoluteAgeThreshold = moment() + .subtract( + dynamicSettings.certAgeThreshold ?? DYNAMIC_SETTINGS_DEFAULTS.certAgeThreshold, + 'd' + ) + .valueOf(); + const alertInstance = alertInstanceFactory(TLS.id); + const summary = getCertSummary(certs, absoluteExpirationThreshold, absoluteAgeThreshold); + alertInstance.replaceState({ + ...updateState(state, foundCerts), + ...summary, + }); + alertInstance.scheduleActions(TLS.id); + } + + return updateState(state, foundCerts); + }, + }); diff --git a/x-pack/plugins/uptime/server/lib/alerts/uptime_alert_wrapper.ts b/x-pack/plugins/uptime/server/lib/alerts/uptime_alert_wrapper.ts index 390b6d347996c1..0961eb6557891e 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/uptime_alert_wrapper.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/uptime_alert_wrapper.ts @@ -4,18 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ILegacyScopedClusterClient, ElasticsearchClient } from 'kibana/server'; +import { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; import { AlertExecutorOptions, AlertType, AlertTypeState } from '../../../../alerts/server'; import { savedObjectsAdapter } from '../saved_objects'; import { DynamicSettings } from '../../../common/runtime_types'; export interface UptimeAlertType extends Omit { - executor: ( - options: AlertExecutorOptions, - callES: ILegacyScopedClusterClient['callAsCurrentUser'], - esClient: ElasticsearchClient, - dynamicSettings: DynamicSettings - ) => Promise; + executor: ({ + options, + esClient, + dynamicSettings, + }: { + options: AlertExecutorOptions; + esClient: ElasticsearchClient; + dynamicSettings: DynamicSettings; + savedObjectsClient: SavedObjectsClientContract; + }) => Promise; } export const uptimeAlertWrapper = (uptimeAlert: UptimeAlertType) => ({ @@ -23,13 +27,13 @@ export const uptimeAlertWrapper = (uptimeAlert: UptimeAlertType) => ({ producer: 'uptime', executor: async (options: AlertExecutorOptions) => { const { - services: { callCluster: callES, scopedClusterClient }, + services: { scopedClusterClient: esClient, savedObjectsClient }, } = options; const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings( options.services.savedObjectsClient ); - return uptimeAlert.executor(options, callES, scopedClusterClient, dynamicSettings); + return uptimeAlert.executor({ options, esClient, dynamicSettings, savedObjectsClient }); }, }); diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_monitor_charts.test.ts.snap b/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_monitor_charts.test.ts.snap index 97b97f84407584..6ab55c2afdddab 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_monitor_charts.test.ts.snap +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_monitor_charts.test.ts.snap @@ -2,7 +2,6 @@ exports[`ElasticsearchMonitorsAdapter getMonitorChartsData will provide expected filters 1`] = ` Array [ - "search", Object { "body": Object { "aggs": Object { @@ -26,9 +25,6 @@ Array [ "buckets": 25, "field": "@timestamp", }, - "date_histogram": Object { - "fixed_interval": "36000ms", - }, }, }, "query": Object { diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts index 4faaed53bebf2f..c0b94b19b75825 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts @@ -6,10 +6,10 @@ import { getCerts } from '../get_certs'; import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../common/constants'; +import { elasticsearchServiceMock } from '../../../../../../../src/core/server/mocks'; describe('getCerts', () => { let mockHits: any; - let mockCallES: jest.Mock; beforeEach(() => { mockHits = [ @@ -79,17 +79,20 @@ describe('getCerts', () => { }, }, ]; - mockCallES = jest.fn(); - mockCallES.mockImplementation(() => ({ - hits: { - hits: mockHits, - }, - })); }); it('parses query result and returns expected values', async () => { + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockEsClient.search.mockResolvedValueOnce({ + body: { + hits: { + hits: mockHits, + }, + }, + } as any); + const result = await getCerts({ - callES: mockCallES, + callES: mockEsClient, dynamicSettings: { heartbeatIndices: 'heartbeat*', certAgeThreshold: DYNAMIC_SETTINGS_DEFAULTS.certAgeThreshold, @@ -126,10 +129,9 @@ describe('getCerts', () => { "total": 0, } `); - expect(mockCallES.mock.calls).toMatchInlineSnapshot(` + expect(mockEsClient.search.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "search", Object { "body": Object { "_source": Array [ diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts index bd353b62df828e..9503174ed104c1 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts @@ -6,6 +6,7 @@ import { getLatestMonitor } from '../get_latest_monitor'; import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../common/constants'; +import { elasticsearchServiceMock } from '../../../../../../../src/core/server/mocks'; describe('getLatestMonitor', () => { let expectedGetLatestSearchParams: any; @@ -44,29 +45,33 @@ describe('getLatestMonitor', () => { }, }; mockEsSearchResult = { - hits: { - hits: [ - { - _id: 'fejwio32', - _source: { - '@timestamp': '123456', - monitor: { - duration: { - us: 12345, + body: { + hits: { + hits: [ + { + _id: 'fejwio32', + _source: { + '@timestamp': '123456', + monitor: { + duration: { + us: 12345, + }, + id: 'testMonitor', + status: 'down', + type: 'http', }, - id: 'testMonitor', - status: 'down', - type: 'http', }, }, - }, - ], + ], + }, }, }; }); it('returns data in expected shape', async () => { - const mockEsClient = jest.fn(async (_request: any, _params: any) => mockEsSearchResult); + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockEsClient.search.mockResolvedValueOnce(mockEsSearchResult); + const result = await getLatestMonitor({ callES: mockEsClient, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, @@ -94,6 +99,6 @@ describe('getLatestMonitor', () => { expect(result.timestamp).toBe('123456'); expect(result.monitor).not.toBeFalsy(); expect(result?.monitor?.id).toBe('testMonitor'); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetLatestSearchParams); + expect(mockEsClient.search).toHaveBeenCalledWith(expectedGetLatestSearchParams); }); }); diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_availability.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_availability.test.ts index 015d9a4925f3eb..e8df65d4101679 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_availability.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_availability.test.ts @@ -72,7 +72,7 @@ const genBucketItem = ({ describe('monitor availability', () => { describe('getMonitorAvailability', () => { it('applies bool filters to params', async () => { - const [callES, esMock] = setupMockEsCompositeQuery< + const esMock = setupMockEsCompositeQuery< AvailabilityKey, GetMonitorAvailabilityResult, AvailabilityDoc @@ -109,16 +109,15 @@ describe('monitor availability', () => { } }`; await getMonitorAvailability({ - callES, + callES: esMock, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, filters: exampleFilter, range: 2, rangeUnit: 'w', threshold: '54', }); - expect(esMock.callAsCurrentUser).toHaveBeenCalledTimes(1); - const [method, params] = esMock.callAsCurrentUser.mock.calls[0]; - expect(method).toEqual('search'); + expect(esMock.search).toHaveBeenCalledTimes(1); + const [params] = esMock.search.mock.calls[0]; expect(params).toMatchInlineSnapshot(` Object { "body": Object { @@ -245,7 +244,7 @@ describe('monitor availability', () => { }); it('fetches a single page of results', async () => { - const [callES, esMock] = setupMockEsCompositeQuery< + const esMock = setupMockEsCompositeQuery< AvailabilityKey, GetMonitorAvailabilityResult, AvailabilityDoc @@ -288,13 +287,12 @@ describe('monitor availability', () => { threshold: '69', }; const result = await getMonitorAvailability({ - callES, + callES: esMock, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, ...clientParameters, }); - expect(esMock.callAsCurrentUser).toHaveBeenCalledTimes(1); - const [method, params] = esMock.callAsCurrentUser.mock.calls[0]; - expect(method).toEqual('search'); + expect(esMock.search).toHaveBeenCalledTimes(1); + const [params] = esMock.search.mock.calls[0]; expect(params).toMatchInlineSnapshot(` Object { "body": Object { @@ -458,7 +456,7 @@ describe('monitor availability', () => { }); it('fetches multiple pages', async () => { - const [callES, esMock] = setupMockEsCompositeQuery< + const esMock = setupMockEsCompositeQuery< AvailabilityKey, GetMonitorAvailabilityResult, AvailabilityDoc @@ -512,7 +510,7 @@ describe('monitor availability', () => { genBucketItem ); const result = await getMonitorAvailability({ - callES, + callES: esMock, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, range: 3, rangeUnit: 'M', @@ -606,9 +604,8 @@ describe('monitor availability', () => { }, ] `); - const [method, params] = esMock.callAsCurrentUser.mock.calls[0]; - expect(esMock.callAsCurrentUser).toHaveBeenCalledTimes(2); - expect(method).toEqual('search'); + const [params] = esMock.search.mock.calls[0]; + expect(esMock.search).toHaveBeenCalledTimes(2); expect(params).toMatchInlineSnapshot(` Object { "body": Object { @@ -701,9 +698,9 @@ describe('monitor availability', () => { "index": "heartbeat-8*", } `); - expect(esMock.callAsCurrentUser.mock.calls[1]).toMatchInlineSnapshot(` + + expect(esMock.search.mock.calls[1]).toMatchInlineSnapshot(` Array [ - "search", Object { "body": Object { "aggs": Object { @@ -803,7 +800,7 @@ describe('monitor availability', () => { }); it('does not overwrite filters', async () => { - const [callES, esMock] = setupMockEsCompositeQuery< + const esMock = setupMockEsCompositeQuery< AvailabilityKey, GetMonitorAvailabilityResult, AvailabilityDoc @@ -816,14 +813,14 @@ describe('monitor availability', () => { genBucketItem ); await getMonitorAvailability({ - callES, + callES: esMock, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, range: 3, rangeUnit: 's', threshold: '99', filters: JSON.stringify({ bool: { filter: [{ term: { 'monitor.id': 'foo' } }] } }), }); - const [, params] = esMock.callAsCurrentUser.mock.calls[0]; + const [params] = esMock.search.mock.calls[0]; expect(params).toMatchInlineSnapshot(` Object { "body": Object { diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_charts.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_charts.test.ts index 2ebe670bc43c1d..9edd3e2e160d24 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_charts.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_charts.test.ts @@ -8,37 +8,37 @@ import { set } from '@elastic/safer-lodash-set'; import mockChartsData from './monitor_charts_mock.json'; import { getMonitorDurationChart } from '../get_monitor_duration'; import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../common/constants'; +import { elasticsearchServiceMock } from '../../../../../../../src/core/server/mocks'; describe('ElasticsearchMonitorsAdapter', () => { it('getMonitorChartsData will provide expected filters', async () => { expect.assertions(2); - const searchMock = jest.fn(); - const search = searchMock.bind({}); + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); await getMonitorDurationChart({ - callES: search, + callES: mockEsClient, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, monitorId: 'fooID', dateStart: 'now-15m', dateEnd: 'now', }); - expect(searchMock).toHaveBeenCalledTimes(1); + expect(mockEsClient.search).toHaveBeenCalledTimes(1); // protect against possible rounding errors polluting the snapshot comparison set( - searchMock.mock.calls[0][1], + mockEsClient.search.mock.calls[0], 'body.aggs.timeseries.date_histogram.fixed_interval', '36000ms' ); - expect(searchMock.mock.calls[0]).toMatchSnapshot(); + expect(mockEsClient.search.mock.calls[0]).toMatchSnapshot(); }); it('inserts empty buckets for missing data', async () => { - const searchMock = jest.fn(); - searchMock.mockReturnValue(mockChartsData); - const search = searchMock.bind({}); + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockEsClient.search.mockResolvedValueOnce(mockChartsData as any); + expect( await getMonitorDurationChart({ - callES: search, + callES: mockEsClient, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, monitorId: 'id', dateStart: 'now-15m', diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts index e61d736e371061..949bc39f072593 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts @@ -42,7 +42,7 @@ const genBucketItem = ({ describe('getMonitorStatus', () => { it('applies bool filters to params', async () => { - const [callES, esMock] = setupMockEsCompositeQuery( + const esMock = setupMockEsCompositeQuery( [], genBucketItem ); @@ -78,7 +78,7 @@ describe('getMonitorStatus', () => { }, }; await getMonitorStatus({ - callES, + callES: esMock, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, filters: exampleFilter, locations: [], @@ -88,9 +88,8 @@ describe('getMonitorStatus', () => { to: 'now-1m', }, }); - expect(esMock.callAsCurrentUser).toHaveBeenCalledTimes(1); - const [method, params] = esMock.callAsCurrentUser.mock.calls[0]; - expect(method).toEqual('search'); + expect(esMock.search).toHaveBeenCalledTimes(1); + const [params] = esMock.search.mock.calls[0]; expect(params).toMatchInlineSnapshot(` Object { "body": Object { @@ -190,12 +189,12 @@ describe('getMonitorStatus', () => { }); it('applies locations to params', async () => { - const [callES, esMock] = setupMockEsCompositeQuery( + const esMock = setupMockEsCompositeQuery( [], genBucketItem ); await getMonitorStatus({ - callES, + callES: esMock, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, locations: ['fairbanks', 'harrisburg'], numTimes: 1, @@ -204,9 +203,8 @@ describe('getMonitorStatus', () => { to: 'now', }, }); - expect(esMock.callAsCurrentUser).toHaveBeenCalledTimes(1); - const [method, params] = esMock.callAsCurrentUser.mock.calls[0]; - expect(method).toEqual('search'); + expect(esMock.search).toHaveBeenCalledTimes(1); + const [params] = esMock.search.mock.calls[0]; expect(params).toMatchInlineSnapshot(` Object { "body": Object { @@ -291,7 +289,7 @@ describe('getMonitorStatus', () => { }); it('properly assigns filters for complex kuery filters', async () => { - const [callES, esMock] = setupMockEsCompositeQuery( + const esMock = setupMockEsCompositeQuery( [{ bucketCriteria: [] }], genBucketItem ); @@ -353,12 +351,12 @@ describe('getMonitorStatus', () => { }, }; await getMonitorStatus({ - callES, + callES: esMock, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, ...clientParameters, }); - expect(esMock.callAsCurrentUser).toHaveBeenCalledTimes(1); - const [, params] = esMock.callAsCurrentUser.mock.calls[0]; + expect(esMock.search).toHaveBeenCalledTimes(1); + const [params] = esMock.search.mock.calls[0]; expect(params).toMatchInlineSnapshot(` Object { "body": Object { @@ -476,7 +474,7 @@ describe('getMonitorStatus', () => { }); it('properly assigns filters for complex kuery filters object', async () => { - const [callES, esMock] = setupMockEsCompositeQuery( + const esMock = setupMockEsCompositeQuery( [{ bucketCriteria: [] }], genBucketItem ); @@ -498,12 +496,12 @@ describe('getMonitorStatus', () => { }, }; await getMonitorStatus({ - callES, + callES: esMock, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, ...clientParameters, }); - expect(esMock.callAsCurrentUser).toHaveBeenCalledTimes(1); - const [, params] = esMock.callAsCurrentUser.mock.calls[0]; + expect(esMock.search).toHaveBeenCalledTimes(1); + const [params] = esMock.search.mock.calls[0]; expect(params).toMatchInlineSnapshot(` Object { "body": Object { @@ -581,7 +579,7 @@ describe('getMonitorStatus', () => { }); it('fetches single page of results', async () => { - const [callES, esMock] = setupMockEsCompositeQuery( + const esMock = setupMockEsCompositeQuery( [ { bucketCriteria: [ @@ -618,13 +616,12 @@ describe('getMonitorStatus', () => { }, }; const result = await getMonitorStatus({ - callES, + callES: esMock, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, ...clientParameters, }); - expect(esMock.callAsCurrentUser).toHaveBeenCalledTimes(1); - const [method, params] = esMock.callAsCurrentUser.mock.calls[0]; - expect(method).toEqual('search'); + expect(esMock.search).toHaveBeenCalledTimes(1); + const [params] = esMock.search.mock.calls[0]; expect(params).toMatchInlineSnapshot(` Object { "body": Object { @@ -792,12 +789,12 @@ describe('getMonitorStatus', () => { ], }, ]; - const [callES] = setupMockEsCompositeQuery( + const esMock = setupMockEsCompositeQuery( criteria, genBucketItem ); const result = await getMonitorStatus({ - callES, + callES: esMock, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, locations: [], numTimes: 5, diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts index ac940ffb6676f0..86e5f2876ca28b 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts @@ -6,6 +6,7 @@ import { getPingHistogram } from '../get_ping_histogram'; import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../common/constants'; +import { elasticsearchServiceMock } from '../../../../../../../src/core/server/mocks'; describe('getPingHistogram', () => { const standardMockResponse: any = { @@ -37,25 +38,28 @@ describe('getPingHistogram', () => { it.skip('returns a single bucket if array has 1', async () => { expect.assertions(2); - const mockEsClient = jest.fn(); - mockEsClient.mockReturnValue({ - aggregations: { - timeseries: { - buckets: [ - { - key: 1, - up: { - doc_count: 2, + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + + mockEsClient.search.mockResolvedValueOnce({ + body: { + aggregations: { + timeseries: { + buckets: [ + { + key: 1, + up: { + doc_count: 2, + }, + down: { + doc_count: 1, + }, }, - down: { - doc_count: 1, - }, - }, - ], - interval: '10s', + ], + interval: '10s', + }, }, }, - }); + } as any); const result = await getPingHistogram({ callES: mockEsClient, @@ -64,16 +68,20 @@ describe('getPingHistogram', () => { to: 'now', }); - expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.search).toHaveBeenCalledTimes(1); expect(result).toMatchSnapshot(); }); it('returns expected result for no status filter', async () => { expect.assertions(2); - const mockEsClient = jest.fn(); + + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); standardMockResponse.aggregations.timeseries.interval = '1m'; - mockEsClient.mockReturnValue(standardMockResponse); + + mockEsClient.search.mockResolvedValueOnce({ + body: standardMockResponse, + } as any); const result = await getPingHistogram({ callES: mockEsClient, @@ -83,50 +91,53 @@ describe('getPingHistogram', () => { filters: '', }); - expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.search).toHaveBeenCalledTimes(1); expect(result).toMatchSnapshot(); }); it('handles status + additional user queries', async () => { expect.assertions(2); - const mockEsClient = jest.fn(); - - mockEsClient.mockReturnValue({ - aggregations: { - timeseries: { - buckets: [ - { - key: 1, - up: { - doc_count: 2, - }, - down: { - doc_count: 1, - }, - }, - { - key: 2, - up: { - doc_count: 2, - }, - down: { - doc_count: 2, + + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + + mockEsClient.search.mockResolvedValueOnce({ + body: { + aggregations: { + timeseries: { + buckets: [ + { + key: 1, + up: { + doc_count: 2, + }, + down: { + doc_count: 1, + }, }, - }, - { - key: 3, - up: { - doc_count: 3, + { + key: 2, + up: { + doc_count: 2, + }, + down: { + doc_count: 2, + }, }, - down: { - doc_count: 1, + { + key: 3, + up: { + doc_count: 3, + }, + down: { + doc_count: 1, + }, }, - }, - ], - interval: '1h', + ], + interval: '1h', + }, }, }, - }); + } as any); const searchFilter = { bool: { @@ -146,50 +157,52 @@ describe('getPingHistogram', () => { monitorId: undefined, }); - expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.search).toHaveBeenCalledTimes(1); expect(result).toMatchSnapshot(); }); it('handles simple_text_query without issues', async () => { expect.assertions(2); - const mockEsClient = jest.fn(); - - mockEsClient.mockReturnValue({ - aggregations: { - timeseries: { - buckets: [ - { - key: 1, - up: { - doc_count: 2, + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + + mockEsClient.search.mockResolvedValueOnce({ + body: { + aggregations: { + timeseries: { + buckets: [ + { + key: 1, + up: { + doc_count: 2, + }, + down: { + doc_count: 1, + }, }, - down: { - doc_count: 1, + { + key: 2, + up: { + doc_count: 1, + }, + down: { + doc_count: 2, + }, }, - }, - { - key: 2, - up: { - doc_count: 1, - }, - down: { - doc_count: 2, + { + key: 3, + up: { + doc_count: 3, + }, + down: { + doc_count: 1, + }, }, - }, - { - key: 3, - up: { - doc_count: 3, - }, - down: { - doc_count: 1, - }, - }, - ], - interval: '1m', + ], + interval: '1m', + }, }, }, - }); + } as any); const filters = `{"bool":{"must":[{"simple_query_string":{"query":"http"}}]}}`; const result = await getPingHistogram({ @@ -200,7 +213,7 @@ describe('getPingHistogram', () => { filters, }); - expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.search).toHaveBeenCalledTimes(1); expect(result).toMatchSnapshot(); }); }); diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts index cb84cc2eb05b6e..f313cce9f758bb 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts @@ -7,6 +7,7 @@ import { getPings } from '../get_pings'; import { set } from '@elastic/safer-lodash-set'; import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../common/constants'; +import { elasticsearchServiceMock } from '../../../../../../../src/core/server/mocks'; describe('getAll', () => { let mockEsSearchResult: any; @@ -49,15 +50,17 @@ describe('getAll', () => { }, ]; mockEsSearchResult = { - hits: { - total: { - value: mockHits.length, + body: { + hits: { + total: { + value: mockHits.length, + }, + hits: mockHits, }, - hits: mockHits, - }, - aggregations: { - locations: { - buckets: [{ key: 'foo' }], + aggregations: { + locations: { + buckets: [{ key: 'foo' }], + }, }, }, }; @@ -84,8 +87,9 @@ describe('getAll', () => { }); it('returns data in the appropriate shape', async () => { - const mockEsClient = jest.fn(); - mockEsClient.mockReturnValue(mockEsSearchResult); + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + + mockEsClient.search.mockResolvedValueOnce(mockEsSearchResult); const result = await getPings({ callES: mockEsClient, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, @@ -102,12 +106,12 @@ describe('getAll', () => { expect(pings[0].timestamp).toBe('2018-10-30T18:51:59.792Z'); expect(pings[1].timestamp).toBe('2018-10-30T18:53:59.792Z'); expect(pings[2].timestamp).toBe('2018-10-30T18:55:59.792Z'); - expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.search).toHaveBeenCalledTimes(1); }); it('creates appropriate sort and size parameters', async () => { - const mockEsClient = jest.fn(); - mockEsClient.mockReturnValue(mockEsSearchResult); + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockEsClient.search.mockResolvedValueOnce(mockEsSearchResult); await getPings({ callES: mockEsClient, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, @@ -117,10 +121,9 @@ describe('getAll', () => { }); set(expectedGetAllParams, 'body.sort[0]', { timestamp: { order: 'asc' } }); - expect(mockEsClient).toHaveBeenCalledTimes(1); - expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockEsClient.search.mock.calls[0]).toMatchInlineSnapshot(` Array [ - "search", Object { "body": Object { "aggregations": Object { @@ -186,8 +189,8 @@ describe('getAll', () => { }); it('omits the sort param when no sort passed', async () => { - const mockEsClient = jest.fn(); - mockEsClient.mockReturnValue(mockEsSearchResult); + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockEsClient.search.mockResolvedValueOnce(mockEsSearchResult); await getPings({ callES: mockEsClient, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, @@ -195,10 +198,9 @@ describe('getAll', () => { size: 12, }); - expect(mockEsClient).toHaveBeenCalledTimes(1); - expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockEsClient.search.mock.calls[0]).toMatchInlineSnapshot(` Array [ - "search", Object { "body": Object { "aggregations": Object { @@ -264,8 +266,8 @@ describe('getAll', () => { }); it('omits the size param when no size passed', async () => { - const mockEsClient = jest.fn(); - mockEsClient.mockReturnValue(mockEsSearchResult); + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockEsClient.search.mockResolvedValueOnce(mockEsSearchResult); await getPings({ callES: mockEsClient, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, @@ -273,10 +275,9 @@ describe('getAll', () => { sort: 'desc', }); - expect(mockEsClient).toHaveBeenCalledTimes(1); - expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockEsClient.search.mock.calls[0]).toMatchInlineSnapshot(` Array [ - "search", Object { "body": Object { "aggregations": Object { @@ -342,8 +343,8 @@ describe('getAll', () => { }); it('adds a filter for monitor ID', async () => { - const mockEsClient = jest.fn(); - mockEsClient.mockReturnValue(mockEsSearchResult); + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockEsClient.search.mockResolvedValueOnce(mockEsSearchResult); await getPings({ callES: mockEsClient, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, @@ -351,10 +352,9 @@ describe('getAll', () => { monitorId: 'testmonitorid', }); - expect(mockEsClient).toHaveBeenCalledTimes(1); - expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockEsClient.search.mock.calls[0]).toMatchInlineSnapshot(` Array [ - "search", Object { "body": Object { "aggregations": Object { @@ -425,8 +425,8 @@ describe('getAll', () => { }); it('adds a filter for monitor status', async () => { - const mockEsClient = jest.fn(); - mockEsClient.mockReturnValue(mockEsSearchResult); + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockEsClient.search.mockResolvedValueOnce(mockEsSearchResult); await getPings({ callES: mockEsClient, dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, @@ -434,10 +434,9 @@ describe('getAll', () => { status: 'down', }); - expect(mockEsClient).toHaveBeenCalledTimes(1); - expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockEsClient.search.mock.calls[0]).toMatchInlineSnapshot(` Array [ - "search", Object { "body": Object { "aggregations": Object { diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/helper.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/helper.ts index 878569b5d390f0..4ebc9b2da78558 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/helper.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/helper.ts @@ -4,16 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LegacyScopedClusterClient } from 'src/core/server'; import { elasticsearchServiceMock } from '../../../../../../../src/core/server/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ElasticsearchClientMock } from '../../../../../../../src/core/server/elasticsearch/client/mocks'; + export interface MultiPageCriteria { after_key?: K; bucketCriteria: T[]; } -export type MockCallES = (method: any, params: any) => Promise; - /** * This utility function will set up a mock ES client, and store subsequent calls. It is designed * to let callers easily simulate an arbitrary series of chained composite aggregation calls by supplying @@ -30,8 +30,8 @@ export type MockCallES = (method: any, params: any) => Promise; export const setupMockEsCompositeQuery = ( criteria: Array>, genBucketItem: (criteria: C) => I -): [MockCallES, jest.Mocked>] => { - const esMock = elasticsearchServiceMock.createLegacyScopedClusterClient(); +): ElasticsearchClientMock => { + const esMock = elasticsearchServiceMock.createElasticsearchClient(); // eslint-disable-next-line @typescript-eslint/naming-convention criteria.forEach(({ after_key, bucketCriteria }) => { @@ -43,8 +43,14 @@ export const setupMockEsCompositeQuery = ( }, }, }; - esMock.callAsCurrentUser.mockResolvedValueOnce(mockResponse); + esMock.search.mockResolvedValueOnce({ + body: mockResponse, + statusCode: 200, + headers: {}, + warnings: [], + meta: {} as any, + }); }); - return [(method: any, params: any) => esMock.callAsCurrentUser(method, params), esMock]; + return esMock; }; diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/monitor_charts_mock.json b/x-pack/plugins/uptime/server/lib/requests/__tests__/monitor_charts_mock.json index c62e862a9af89a..9fbfdb98d7fa44 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/monitor_charts_mock.json +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/monitor_charts_mock.json @@ -1,146 +1,318 @@ { - "took": 40, - "timed_out": false, - "_shards": { - "total": 1, - "successful": 1, - "skipped": 0, - "failed": 0 - }, - "aggregations": { - "timeseries": { - "buckets": [ - { - "key": 1568411568000, - "doc_count": 4, - "location": { - "buckets": [ - { "key": "us-east-2", "duration": { "avg": 4658759 } }, - { "key": "us-west-4", "duration": { "avg": 8678399.5 } } - ] + "body": { + "took": 40, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "aggregations": { + "timeseries": { + "buckets": [ + { + "key": 1568411568000, + "doc_count": 4, + "location": { + "buckets": [ + { + "key": "us-east-2", + "duration": { + "avg": 4658759 + } + }, + { + "key": "us-west-4", + "duration": { + "avg": 8678399.5 + } + } + ] + } + }, + { + "key": 1568411604000, + "doc_count": 0, + "location": { + "buckets": [] + } + }, + { + "key": 1568411640000, + "doc_count": 8, + "location": { + "buckets": [ + { + "key": "us-east-2", + "duration": { + "avg": 481780 + } + }, + { + "key": "us-west-4", + "duration": { + "avg": 685056.5 + } + } + ] + } + }, + { + "key": 1568411784000, + "doc_count": 8, + "location": { + "buckets": [ + { + "key": "us-east-2", + "duration": { + "avg": 469206.5 + } + }, + { + "key": "us-west-4", + "duration": { + "avg": 261406.5 + } + } + ] + } + }, + { + "key": 1568411820000, + "doc_count": 0, + "location": { + "buckets": [] + } + }, + { + "key": 1568411856000, + "doc_count": 0, + "location": { + "buckets": [] + } + }, + { + "key": 1568411892000, + "doc_count": 0, + "location": { + "buckets": [] + } + }, + { + "key": 1568411928000, + "doc_count": 4, + "location": { + "buckets": [ + { + "key": "us-west-4", + "duration": { + "avg": 1999309.6666667 + } + }, + { + "key": "us-east-2", + "duration": { + "avg": 645563 + } + } + ] + } + }, + { + "key": 1568411964000, + "doc_count": 7, + "location": { + "buckets": [ + { + "key": "us-west-4", + "duration": { + "avg": 2499799.25 + } + }, + { + "key": "us-east-2", + "duration": { + "avg": 1513896.6666667 + } + } + ] + } + }, + { + "key": 1568412036000, + "doc_count": 5, + "location": { + "buckets": [ + { + "key": "us-west-4", + "duration": { + "avg": 1876155.3333333 + } + }, + { + "key": "us-east-2", + "duration": { + "avg": 1511409 + } + } + ] + } + }, + { + "key": 1568412072000, + "doc_count": 4, + "location": { + "buckets": [ + { + "key": "us-west-4", + "duration": { + "avg": 1490845.75 + } + } + ] + } + }, + { + "key": 1568412108000, + "doc_count": 3, + "location": { + "buckets": [ + { + "key": "us-west-4", + "duration": { + "avg": 2365962.6666667 + } + } + ] + } + }, + { + "key": 1568412144000, + "doc_count": 4, + "location": { + "buckets": [ + { + "key": "us-west-4", + "duration": { + "avg": 1788901.25 + } + } + ] + } + }, + { + "key": 1568412180000, + "doc_count": 4, + "location": { + "buckets": [ + { + "key": "us-west-4", + "duration": { + "avg": 1773177.5 + } + } + ] + } + }, + { + "key": 1568412216000, + "doc_count": 3, + "location": { + "buckets": [ + { + "key": "us-west-4", + "duration": { + "avg": 3086220.3333333 + } + } + ] + } + }, + { + "key": 1568412252000, + "doc_count": 1, + "location": { + "buckets": [ + { + "key": "us-west-4", + "duration": { + "avg": 1020528 + } + } + ] + } + }, + { + "key": 1568412288000, + "doc_count": 3, + "location": { + "buckets": [ + { + "key": "us-west-4", + "duration": { + "avg": 1643963.3333333 + } + } + ] + } + }, + { + "key": 1568412324000, + "doc_count": 8, + "location": { + "buckets": [ + { + "key": "us-east-2", + "duration": { + "avg": 1804116 + } + }, + { + "key": "us-west-4", + "duration": { + "avg": 1799630 + } + } + ] + } + }, + { + "key": 1568412432000, + "doc_count": 8, + "location": { + "buckets": [ + { + "key": "us-east-2", + "duration": { + "avg": 1972483.25 + } + }, + { + "key": "us-west-4", + "duration": { + "avg": 1543307.5 + } + } + ] + } + }, + { + "key": 1568412468000, + "doc_count": 1, + "location": { + "buckets": [ + { + "key": "us-east-2", + "duration": { + "avg": 1020490 + } + } + ] + } } - }, - { "key": 1568411604000, "doc_count": 0, "location": { "buckets": [] } }, - { - "key": 1568411640000, - "doc_count": 8, - "location": { - "buckets": [ - { "key": "us-east-2", "duration": { "avg": 481780 } }, - { "key": "us-west-4", "duration": { "avg": 685056.5 } } - ] - } - }, - { - "key": 1568411784000, - "doc_count": 8, - "location": { - "buckets": [ - { "key": "us-east-2", "duration": { "avg": 469206.5 } }, - { "key": "us-west-4", "duration": { "avg": 261406.5 } } - ] - } - }, - { "key": 1568411820000, "doc_count": 0, "location": { "buckets": [] } }, - { "key": 1568411856000, "doc_count": 0, "location": { "buckets": [] } }, - { "key": 1568411892000, "doc_count": 0, "location": { "buckets": [] } }, - { - "key": 1568411928000, - "doc_count": 4, - "location": { - "buckets": [ - { "key": "us-west-4", "duration": { "avg": 1999309.6666667 } }, - { "key": "us-east-2", "duration": { "avg": 645563 } } - ] - } - }, - { - "key": 1568411964000, - "doc_count": 7, - "location": { - "buckets": [ - { "key": "us-west-4", "duration": { "avg": 2499799.25 } }, - { "key": "us-east-2", "duration": { "avg": 1513896.6666667 } } - ] - } - }, - { - "key": 1568412036000, - "doc_count": 5, - "location": { - "buckets": [ - { "key": "us-west-4", "duration": { "avg": 1876155.3333333 } }, - { "key": "us-east-2", "duration": { "avg": 1511409 } } - ] - } - }, - { - "key": 1568412072000, - "doc_count": 4, - "location": { "buckets": [{ "key": "us-west-4", "duration": { "avg": 1490845.75 } }] } - }, - { - "key": 1568412108000, - "doc_count": 3, - "location": { - "buckets": [{ "key": "us-west-4", "duration": { "avg": 2365962.6666667 } }] - } - }, - { - "key": 1568412144000, - "doc_count": 4, - "location": { "buckets": [{ "key": "us-west-4", "duration": { "avg": 1788901.25 } }] } - }, - { - "key": 1568412180000, - "doc_count": 4, - "location": { "buckets": [{ "key": "us-west-4", "duration": { "avg": 1773177.5 } }] } - }, - { - "key": 1568412216000, - "doc_count": 3, - "location": { - "buckets": [{ "key": "us-west-4", "duration": { "avg": 3086220.3333333 } }] - } - }, - { - "key": 1568412252000, - "doc_count": 1, - "location": { "buckets": [{ "key": "us-west-4", "duration": { "avg": 1020528 } }] } - }, - { - "key": 1568412288000, - "doc_count": 3, - "location": { - "buckets": [{ "key": "us-west-4", "duration": { "avg": 1643963.3333333 } }] - } - }, - { - "key": 1568412324000, - "doc_count": 8, - "location": { - "buckets": [ - { "key": "us-east-2", "duration": { "avg": 1804116 } }, - { "key": "us-west-4", "duration": { "avg": 1799630 } } - ] - } - }, - { - "key": 1568412432000, - "doc_count": 8, - "location": { - "buckets": [ - { "key": "us-east-2", "duration": { "avg": 1972483.25 } }, - { "key": "us-west-4", "duration": { "avg": 1543307.5 } } - ] - } - }, - { - "key": 1568412468000, - "doc_count": 1, - "location": { "buckets": [{ "key": "us-east-2", "duration": { "avg": 1020490 } }] } - } - ] + ] + } } } } diff --git a/x-pack/plugins/uptime/server/lib/requests/get_certs.ts b/x-pack/plugins/uptime/server/lib/requests/get_certs.ts index 4793d420cbfd83..0836cb039b215e 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_certs.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_certs.ts @@ -145,7 +145,7 @@ export const getCerts: UMElasticsearchQueryFn = asyn } // console.log(JSON.stringify(params, null, 2)); - const result = await callES('search', params); + const { body: result } = await callES.search(params); const certs = (result?.hits?.hits ?? []).map((hit: any) => { const { diff --git a/x-pack/plugins/uptime/server/lib/requests/get_filter_bar.ts b/x-pack/plugins/uptime/server/lib/requests/get_filter_bar.ts index e89b457eccf32d..c3295d6dd9c8f7 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_filter_bar.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_filter_bar.ts @@ -93,6 +93,8 @@ export const getFilterBar: UMElasticsearchQueryFn = async ({ esClient, dynamicSettings }) => { +export const getUptimeIndexPattern = async ({ + esClient, + dynamicSettings, +}: { + esClient: ElasticsearchClient; + dynamicSettings: DynamicSettings; +}): Promise => { const indexPatternsFetcher = new IndexPatternsFetcher(esClient); // Since `getDynamicIndexPattern` is called in setup_request (and thus by every endpoint) @@ -28,12 +31,10 @@ export const getUptimeIndexPattern: UMElasticsearchQueryFn< pattern: dynamicSettings.heartbeatIndices, }); - const indexPattern: IndexPatternTitleAndFields = { + return { fields, title: dynamicSettings.heartbeatIndices, }; - - return indexPattern; } catch (e) { const notExists = e.output?.statusCode === 404; if (notExists) { diff --git a/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts b/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts index 7688f04f1acd95..061d002b010de4 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts @@ -12,9 +12,11 @@ export const getIndexStatus: UMElasticsearchQueryFn<{}, StatesIndexStatus> = asy dynamicSettings, }) => { const { - _shards: { total }, - count, - } = await callES('count', { index: dynamicSettings.heartbeatIndices }); + body: { + _shards: { total }, + count, + }, + } = await callES.count({ index: dynamicSettings.heartbeatIndices }); return { indexExists: total > 0, docCount: count, diff --git a/x-pack/plugins/uptime/server/lib/requests/get_journey_screenshot.ts b/x-pack/plugins/uptime/server/lib/requests/get_journey_screenshot.ts index f726ef47915b89..bff3aaf1176df3 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_journey_screenshot.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_journey_screenshot.ts @@ -42,7 +42,7 @@ export const getJourneyScreenshot: UMElasticsearchQueryFn< _source: ['synthetics.blob'], }, }; - const result = await callES('search', params); + const { body: result } = await callES.search(params); if (!Array.isArray(result?.hits?.hits) || result.hits.hits.length < 1) { return null; } diff --git a/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts b/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts index 9c139b2ce85886..f36815a747db3d 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts @@ -42,7 +42,7 @@ export const getJourneySteps: UMElasticsearchQueryFn h?._source?.synthetics?.type === 'step/screenshot') .map((h: any) => h?._source?.synthetics?.step?.index); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts index d32b78bdc71394..f6562eaa42e900 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts @@ -57,7 +57,7 @@ export const getLatestMonitor: UMElasticsearchQueryFn { +const getMonitorAlerts = async ({ + callES, + dynamicSettings, + alertsClient, + monitorId, +}: { + callES: ElasticsearchClient; + dynamicSettings: any; + alertsClient: any; + monitorId: string; +}) => { const options: any = { page: 1, perPage: 500, @@ -70,13 +73,12 @@ const getMonitorAlerts = async ( const parsedFilters = await formatFilterString( dynamicSettings, callES, - esClient, currAlert.params.filters, currAlert.params.search ); esParams.body.query.bool = Object.assign({}, esParams.body.query.bool, parsedFilters?.bool); - const result = await callES('search', esParams); + const { body: result } = await callES.search(esParams); if (result.hits.total.value > 0) { monitorAlerts.push(currAlert); @@ -88,7 +90,7 @@ const getMonitorAlerts = async ( export const getMonitorDetails: UMElasticsearchQueryFn< GetMonitorDetailsParams, MonitorDetails -> = async ({ callES, esClient, dynamicSettings, monitorId, dateStart, dateEnd, alertsClient }) => { +> = async ({ callES, dynamicSettings, monitorId, dateStart, dateEnd, alertsClient }) => { const queryFilters: any = [ { range: { @@ -132,19 +134,19 @@ export const getMonitorDetails: UMElasticsearchQueryFn< }, }; - const result = await callES('search', params); + const { body: result } = await callES.search(params); const data = result.hits.hits[0]?._source; const monitorError: MonitorError | undefined = data?.error; const errorTimestamp: string | undefined = data?.['@timestamp']; - const monAlerts = await getMonitorAlerts( + const monAlerts = await getMonitorAlerts({ callES, - esClient, dynamicSettings, alertsClient, - monitorId - ); + monitorId, + }); + return { monitorId, error: monitorError, diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_duration.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_duration.ts index 00ca1b58783297..77ae7570a96a84 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_duration.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_duration.ts @@ -59,7 +59,7 @@ export const getMonitorDurationChart: UMElasticsearchQueryFn< }, }; - const result = await callES('search', params); + const { body: result } = await callES.search(params); const dateHistogramBuckets: any[] = result?.aggregations?.timeseries?.buckets ?? []; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_locations.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_locations.ts index f52e965d488ea9..b5183ca9ffb9fc 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_locations.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_locations.ts @@ -88,7 +88,7 @@ export const getMonitorLocations: UMElasticsearchQueryFn< }, }; - const result = await callES('search', params); + const { body: result } = await callES.search(params); const locations = result?.aggregations?.location?.buckets ?? []; const getGeo = (locGeo: { name: string; location?: string }) => { diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts index 3e49a32881f542..020fcf5331188d 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts @@ -153,7 +153,7 @@ export const getHistogramForMonitors = async ( }; const result = await queryContext.search(params); - const histoBuckets: any[] = result.aggregations.histogram.buckets; + const histoBuckets: any[] = result.aggregations?.histogram.buckets ?? []; const simplified = histoBuckets.map((histoBucket: any): { timestamp: number; byId: any } => { const byId: { [key: string]: number } = {}; histoBucket.by_id.buckets.forEach((idBucket: any) => { diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts index caf505610e991b..06648d68969c14 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts @@ -133,7 +133,7 @@ export const getMonitorStatus: UMElasticsearchQueryFn< esParams.body.aggs.monitors.composite.after = afterKey; } - const result = await callES('search', esParams); + const { body: result } = await callES.search(esParams); afterKey = result?.aggregations?.monitors?.after_key; monitors = monitors.concat(result?.aggregations?.monitors?.buckets || []); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts b/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts index 5d8706e2fc5f17..4eb2d862cb7023 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts @@ -76,7 +76,7 @@ export const getPingHistogram: UMElasticsearchQueryFn< }, }; - const result = await callES('search', params); + const { body: result } = await callES.search(params); const buckets: HistogramQueryResult[] = result?.aggregations?.timeseries?.buckets ?? []; const histogram = buckets.map((bucket) => { const x: number = bucket.key; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_pings.ts b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts index 03ec2d7343c9ab..e72b16de3d66f4 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_pings.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts @@ -108,9 +108,11 @@ export const getPings: UMElasticsearchQueryFn = a } const { - hits: { hits, total }, - aggregations: aggs, - } = await callES('search', params); + body: { + hits: { hits, total }, + aggregations: aggs, + }, + } = await callES.search(params); const locations = aggs?.locations ?? { buckets: [{ key: 'N/A', doc_count: 0 }] }; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts b/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts index 92295a38cffb4f..ac36585ff09397 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts @@ -39,7 +39,7 @@ export const getSnapshotCount: UMElasticsearchQueryFn => { - const res = await context.search({ + const { body: res } = await context.search({ index: context.heartbeatIndices, body: statusCountBody(await context.dateAndCustomFilters()), }); diff --git a/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts b/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts index 6c229cf30e165f..38e7dabb19941b 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts @@ -19,7 +19,7 @@ export const findPotentialMatches = async ( searchAfter: any, size: number ) => { - const queryResult = await query(queryContext, searchAfter, size); + const { body: queryResult } = await query(queryContext, searchAfter, size); const monitorIds: string[] = []; get(queryResult, 'aggregations.monitors.buckets', []).forEach((b: any) => { const monitorId = b.key.monitor_id; diff --git a/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts b/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts index 5d97e635f3e7d7..96df8ea651c44a 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts @@ -5,13 +5,13 @@ */ import moment from 'moment'; -import { LegacyAPICaller } from 'src/core/server'; +import { ElasticsearchClient } from 'kibana/server'; import { CursorPagination } from './types'; import { parseRelativeDate } from '../../helper'; import { CursorDirection, SortOrder } from '../../../../common/runtime_types'; export class QueryContext { - callES: LegacyAPICaller; + callES: ElasticsearchClient; heartbeatIndices: string; dateRangeStart: string; dateRangeEnd: string; @@ -43,12 +43,12 @@ export class QueryContext { async search(params: any): Promise { params.index = this.heartbeatIndices; - return this.callES('search', params); + return this.callES.search(params); } async count(params: any): Promise { params.index = this.heartbeatIndices; - return this.callES('count', params); + return this.callES.count(params); } async dateAndCustomFilters(): Promise { diff --git a/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts b/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts index a864bfa591424e..6be9f813016f80 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts @@ -23,7 +23,7 @@ export const refinePotentialMatches = async ( return []; } - const queryResult = await query(queryContext, potentialMatchMonitorIDs); + const { body: queryResult } = await query(queryContext, potentialMatchMonitorIDs); return await fullyMatchingIds(queryResult, queryContext.statusFilter); }; diff --git a/x-pack/plugins/uptime/server/rest_api/index_state/get_index_pattern.ts b/x-pack/plugins/uptime/server/rest_api/index_state/get_index_pattern.ts index baf999158a29e4..418cde9e701d50 100644 --- a/x-pack/plugins/uptime/server/rest_api/index_state/get_index_pattern.ts +++ b/x-pack/plugins/uptime/server/rest_api/index_state/get_index_pattern.ts @@ -17,8 +17,7 @@ export const createGetIndexPatternRoute: UMRestApiRouteFactory = (libs: UMServer return response.ok({ body: { ...(await libs.requests.getIndexPattern({ - callES, - esClient: _context.core.elasticsearch.client.asCurrentUser, + esClient: callES, dynamicSettings, })), }, diff --git a/x-pack/plugins/uptime/server/rest_api/monitors/monitor_list.ts b/x-pack/plugins/uptime/server/rest_api/monitors/monitor_list.ts index 0e2c8c180e0e05..7b461060bf4bce 100644 --- a/x-pack/plugins/uptime/server/rest_api/monitors/monitor_list.ts +++ b/x-pack/plugins/uptime/server/rest_api/monitors/monitor_list.ts @@ -25,44 +25,51 @@ export const createMonitorListRoute: UMRestApiRouteFactory = (libs) => ({ tags: ['access:uptime-read'], }, handler: async ({ callES, dynamicSettings }, _context, request, response): Promise => { - const { - dateRangeStart, - dateRangeEnd, - filters, - pagination, - statusFilter, - pageSize, - } = request.query; - - const decodedPagination = pagination - ? JSON.parse(decodeURIComponent(pagination)) - : CONTEXT_DEFAULTS.CURSOR_PAGINATION; - const [indexStatus, { summaries, nextPagePagination, prevPagePagination }] = await Promise.all([ - libs.requests.getIndexStatus({ callES, dynamicSettings }), - libs.requests.getMonitorStates({ - callES, - dynamicSettings, + try { + const { dateRangeStart, dateRangeEnd, - pagination: decodedPagination, - pageSize, filters, - // this is added to make typescript happy, - // this sort of reassignment used to be further downstream but I've moved it here - // because this code is going to be decomissioned soon - statusFilter: statusFilter || undefined, - }), - ]); + pagination, + statusFilter, + pageSize, + } = request.query; + + const decodedPagination = pagination + ? JSON.parse(decodeURIComponent(pagination)) + : CONTEXT_DEFAULTS.CURSOR_PAGINATION; + const [ + indexStatus, + { summaries, nextPagePagination, prevPagePagination }, + ] = await Promise.all([ + libs.requests.getIndexStatus({ callES, dynamicSettings }), + libs.requests.getMonitorStates({ + callES, + dynamicSettings, + dateRangeStart, + dateRangeEnd, + pagination: decodedPagination, + pageSize, + filters, + // this is added to make typescript happy, + // this sort of reassignment used to be further downstream but I've moved it here + // because this code is going to be decomissioned soon + statusFilter: statusFilter || undefined, + }), + ]); - const totalSummaryCount = indexStatus?.docCount ?? 0; + const totalSummaryCount = indexStatus?.docCount ?? 0; - return response.ok({ - body: { - summaries, - nextPagePagination, - prevPagePagination, - totalSummaryCount, - }, - }); + return response.ok({ + body: { + summaries, + nextPagePagination, + prevPagePagination, + totalSummaryCount, + }, + }); + } catch (e) { + return response.internalError({ body: { message: e.message } }); + } }, }); diff --git a/x-pack/plugins/uptime/server/rest_api/monitors/monitors_details.ts b/x-pack/plugins/uptime/server/rest_api/monitors/monitors_details.ts index 8bbb4fcb5575c2..bb54effc0d57e8 100644 --- a/x-pack/plugins/uptime/server/rest_api/monitors/monitors_details.ts +++ b/x-pack/plugins/uptime/server/rest_api/monitors/monitors_details.ts @@ -28,7 +28,6 @@ export const createGetMonitorDetailsRoute: UMRestApiRouteFactory = (libs: UMServ body: { ...(await libs.requests.getMonitorDetails({ callES, - esClient: context.core.elasticsearch.client.asCurrentUser, dynamicSettings, monitorId, dateStart, diff --git a/x-pack/plugins/uptime/server/rest_api/types.ts b/x-pack/plugins/uptime/server/rest_api/types.ts index 589cb82d550f67..5e5f4a2a991cfd 100644 --- a/x-pack/plugins/uptime/server/rest_api/types.ts +++ b/x-pack/plugins/uptime/server/rest_api/types.ts @@ -9,12 +9,13 @@ import { RequestHandler, RouteConfig, RouteMethod, - LegacyCallAPIOptions, SavedObjectsClientContract, RequestHandlerContext, KibanaRequest, KibanaResponseFactory, IKibanaResponse, + IScopedClusterClient, + ElasticsearchClient, } from 'kibana/server'; import { DynamicSettings } from '../../common/runtime_types'; import { UMServerLibs } from '../lib/lib'; @@ -63,11 +64,8 @@ export type UMKibanaRouteWrapper = (uptimeRoute: UptimeRoute) => UMKibanaRoute; * This type can store custom parameters used by the internal Uptime route handlers. */ export interface UMRouteParams { - callES: ( - endpoint: string, - clientParams?: Record, - options?: LegacyCallAPIOptions | undefined - ) => Promise; + callES: ElasticsearchClient; + esClient: IScopedClusterClient; dynamicSettings: DynamicSettings; savedObjectsClient: SavedObjectsClientContract; } diff --git a/x-pack/plugins/uptime/server/rest_api/uptime_route_wrapper.ts b/x-pack/plugins/uptime/server/rest_api/uptime_route_wrapper.ts index 84a85a54afe138..b2f1c7d6424e62 100644 --- a/x-pack/plugins/uptime/server/rest_api/uptime_route_wrapper.ts +++ b/x-pack/plugins/uptime/server/rest_api/uptime_route_wrapper.ts @@ -13,11 +13,11 @@ export const uptimeRouteWrapper: UMKibanaRouteWrapper = (uptimeRoute) => ({ tags: ['access:uptime-read', ...(uptimeRoute?.writeAccess ? ['access:uptime-write'] : [])], }, handler: async (context, request, response) => { - const { callAsCurrentUser: callES } = context.core.elasticsearch.legacy.client; + const { client: esClient } = context.core.elasticsearch; const { client: savedObjectsClient } = context.core.savedObjects; const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings(savedObjectsClient); return uptimeRoute.handler( - { callES, savedObjectsClient, dynamicSettings }, + { callES: esClient.asCurrentUser, esClient, savedObjectsClient, dynamicSettings }, context, request, response