From 0ecd3fae50a72ff60aa2fd077eb48d5b2528bab9 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Tue, 13 Sep 2022 14:07:52 -0400 Subject: [PATCH] [Synthetics] remove hydrating saved objects (#140545) * synthetics - remove hydrating saved objects * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * remove logic to set url back to empty string * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../routes/monitor_cruds/edit_monitor.ts | 6 +- .../hydrate_saved_object.test.ts | 125 -------------- .../hydrate_saved_object.ts | 158 ------------------ .../synthetics_service/synthetics_service.ts | 10 -- 4 files changed, 1 insertion(+), 298 deletions(-) delete mode 100644 x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.test.ts delete mode 100644 x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts index 832c4322a28668..12b958fa3c67d4 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts @@ -20,7 +20,6 @@ import { SyntheticsMonitorWithSecrets, SyntheticsMonitor, ConfigKey, - FormMonitorType, } from '../../../common/runtime_types'; import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types'; import { API_URLS } from '../../../common/constants'; @@ -146,10 +145,7 @@ export const syncEditedMonitor = async ({ const editedSOPromise = savedObjectsClient.update( syntheticsMonitorType, previousMonitor.id, - monitorWithRevision.type === 'browser' && - monitorWithRevision[ConfigKey.FORM_MONITOR_TYPE] !== FormMonitorType.SINGLE - ? { ...monitorWithRevision, urls: '' } - : monitorWithRevision + monitorWithRevision ); const editSyncPromise = syntheticsMonitorClient.editMonitor( diff --git a/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.test.ts deleted file mode 100644 index c2c0412d940c5d..00000000000000 --- a/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { hydrateSavedObjects } from './hydrate_saved_object'; -import { DecryptedSyntheticsMonitorSavedObject } from '../../common/types'; -import { UptimeServerSetup } from '../legacy_uptime/lib/adapters'; -import { getUptimeESMockClient } from '../legacy_uptime/lib/requests/test_helpers'; -import { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; - -import moment from 'moment'; - -describe('hydrateSavedObjects', () => { - const { uptimeEsClient: mockUptimeEsClient, esClient: mockEsClient } = getUptimeESMockClient(); - - const mockMonitorTemplate = { - id: 'my-mock-monitor', - attributes: { - type: 'browser', - name: 'Test Browser Monitor 01', - }, - }; - - const serverMock: UptimeServerSetup = { - uptimeEsClient: mockUptimeEsClient, - authSavedObjectsClient: { - bulkUpdate: jest.fn(), - }, - } as unknown as UptimeServerSetup; - - const toKibanaResponse = (hits: Array<{ _source: Record }>) => ({ - body: { hits: { hits } }, - }); - - beforeEach(() => { - mockUptimeEsClient.baseESClient.security.hasPrivileges = jest - .fn() - .mockResolvedValue({ has_all_requested: true }); - }); - - it.each([['browser'], ['http'], ['tcp']])( - 'hydrates missing data for %s monitors', - async (type) => { - const time = moment(); - const monitor = { - ...mockMonitorTemplate, - attributes: { ...mockMonitorTemplate.attributes, type }, - updated_at: moment(time).subtract(1, 'hour').toISOString(), - } as DecryptedSyntheticsMonitorSavedObject; - - const monitors: DecryptedSyntheticsMonitorSavedObject[] = [monitor]; - - mockEsClient.search.mockResolvedValue( - toKibanaResponse([ - { - _source: { - config_id: monitor.id, - '@timestamp': moment(time).toISOString(), - url: { port: 443, full: 'https://example.com' }, - }, - }, - ]) as unknown as SearchResponse - ); - - await hydrateSavedObjects({ monitors, server: serverMock }); - - expect(serverMock.authSavedObjectsClient?.bulkUpdate).toHaveBeenCalledWith([ - { - ...monitor, - attributes: { - ...monitor.attributes, - 'url.port': 443, - urls: 'https://example.com', - }, - }, - ]); - } - ); - - it.each([['browser'], ['http'], ['tcp']])( - 'does not hydrate when the user does not have permissions', - async (type) => { - const time = moment(); - const monitor = { - ...mockMonitorTemplate, - attributes: { ...mockMonitorTemplate.attributes, type }, - updated_at: moment(time).subtract(1, 'hour').toISOString(), - } as DecryptedSyntheticsMonitorSavedObject; - - const monitors: DecryptedSyntheticsMonitorSavedObject[] = [monitor]; - - mockUptimeEsClient.baseESClient.security.hasPrivileges = jest - .fn() - .mockResolvedValue({ has_all_requested: false }); - - mockEsClient.search.mockResolvedValue( - toKibanaResponse([ - { - _source: { - config_id: monitor.id, - '@timestamp': moment(time).toISOString(), - url: { port: 443, full: 'https://example.com' }, - }, - }, - ]) as unknown as SearchResponse - ); - - await hydrateSavedObjects({ monitors, server: serverMock }); - - expect(serverMock.authSavedObjectsClient?.bulkUpdate).not.toHaveBeenCalledWith([ - { - ...monitor, - attributes: { - ...monitor.attributes, - 'url.port': 443, - urls: 'https://example.com', - }, - }, - ]); - } - ); -}); diff --git a/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts b/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts deleted file mode 100644 index 9f4158248d6bfe..00000000000000 --- a/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import moment from 'moment'; -import type { SecurityIndexPrivilege } from '@elastic/elasticsearch/lib/api/types'; -import { UptimeESClient } from '../legacy_uptime/lib/lib'; -import { UptimeServerSetup } from '../legacy_uptime/lib/adapters'; -import { DecryptedSyntheticsMonitorSavedObject } from '../../common/types'; -import { SyntheticsMonitor, MonitorFields, Ping } from '../../common/runtime_types'; -import { SYNTHETICS_INDEX_PATTERN } from '../../common/constants'; - -export const hydrateSavedObjects = async ({ - monitors, - server, -}: { - monitors: DecryptedSyntheticsMonitorSavedObject[]; - server: UptimeServerSetup; -}) => { - try { - const { uptimeEsClient } = server; - if (!uptimeEsClient) { - return; - } - - const { has_all_requested: hasAllPrivileges } = - await uptimeEsClient.baseESClient.security.hasPrivileges({ - body: { - index: [ - { - names: ['synthetics-*'], - privileges: ['read'] as SecurityIndexPrivilege[], - }, - ], - }, - }); - - if (!hasAllPrivileges) { - return; - } - - const missingInfoIds: string[] = monitors - .filter((monitor) => { - const isBrowserMonitor = monitor.attributes.type === 'browser'; - const isHTTPMonitor = monitor.attributes.type === 'http'; - const isTCPMonitor = monitor.attributes.type === 'tcp'; - - const monitorAttributes = monitor.attributes as MonitorFields; - const isMissingUrls = !monitorAttributes || !monitorAttributes.urls; - const isMissingPort = !monitorAttributes || !monitorAttributes['url.port']; - - const isEnrichableBrowserMonitor = isBrowserMonitor && (isMissingUrls || isMissingPort); - const isEnrichableHttpMonitor = isHTTPMonitor && isMissingPort; - const isEnrichableTcpMonitor = isTCPMonitor && isMissingPort; - - return isEnrichableBrowserMonitor || isEnrichableHttpMonitor || isEnrichableTcpMonitor; - }) - .map(({ id }) => id); - - if (missingInfoIds.length > 0 && server.uptimeEsClient) { - const esDocs: Ping[] = await fetchSampleMonitorDocuments( - server.uptimeEsClient, - missingInfoIds - ); - - const updatedObjects: DecryptedSyntheticsMonitorSavedObject[] = []; - monitors - .filter((monitor) => missingInfoIds.includes(monitor.id)) - .forEach((monitor) => { - let resultAttributes: SyntheticsMonitor = monitor.attributes; - - let isUpdated = false; - - esDocs.forEach((doc) => { - // to make sure the document is ingested after the latest update of the monitor - const documentIsAfterLatestUpdate = moment(monitor.updated_at).isBefore( - moment(doc.timestamp) - ); - if (!documentIsAfterLatestUpdate) return monitor; - if (doc.config_id !== monitor.id) return monitor; - - if (doc.url?.full) { - isUpdated = true; - resultAttributes = { ...resultAttributes, urls: doc.url?.full }; - } - - if (doc.url?.port) { - isUpdated = true; - resultAttributes = { ...resultAttributes, ['url.port']: doc.url?.port }; - } - }); - if (isUpdated) { - updatedObjects.push({ - ...monitor, - attributes: resultAttributes, - } as DecryptedSyntheticsMonitorSavedObject); - } - }); - - await server.authSavedObjectsClient?.bulkUpdate( - updatedObjects - ); - } - } catch (e) { - server.logger.error(e); - } -}; - -const fetchSampleMonitorDocuments = async (esClient: UptimeESClient, configIds: string[]) => { - const data = await esClient.search( - { - body: { - query: { - bool: { - filter: [ - { - range: { - '@timestamp': { - gte: 'now-15m', - lt: 'now', - }, - }, - }, - { - terms: { - config_id: configIds, - }, - }, - { - exists: { - field: 'summary', - }, - }, - { - bool: { - minimum_should_match: 1, - should: [{ exists: { field: 'url.full' } }, { exists: { field: 'url.port' } }], - }, - }, - ], - }, - }, - _source: ['url', 'config_id', '@timestamp'], - collapse: { - field: 'config_id', - }, - }, - }, - 'getHydrateQuery', - SYNTHETICS_INDEX_PATTERN - ); - return data.body.hits.hits.map( - ({ _source: doc }) => ({ ...(doc as any), timestamp: (doc as any)['@timestamp'] } as Ping) - ); -}; 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 908584a7be03ec..60c98bd5cc1c9d 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts @@ -42,8 +42,6 @@ import { HeartbeatConfig, } from '../../common/runtime_types'; import { getServiceLocations } from './get_service_locations'; -import { hydrateSavedObjects } from './hydrate_saved_object'; -import { DecryptedSyntheticsMonitorSavedObject } from '../../common/types'; import { normalizeSecrets } from './utils/secrets'; @@ -475,14 +473,6 @@ export class SyntheticsService { monitors: monitors.length, }); - if (this.indexTemplateExists) { - // without mapping, querying won't make sense - hydrateSavedObjects({ - monitors: monitors as unknown as DecryptedSyntheticsMonitorSavedObject[], - server: this.server, - }); - } - return (monitors ?? []).map((monitor) => { const attributes = monitor.attributes as unknown as MonitorFields; return formatHeartbeatRequest({