From aacebdba5bf742e962ad7fe164ed3da3e5539f90 Mon Sep 17 00:00:00 2001 From: Abdul Wahab Zahid Date: Tue, 21 Dec 2021 17:56:04 +0100 Subject: [PATCH] [Uptime][Monitor Management] Fix formatter to pass `false` fields through to synthetics service. (#121451) * Fix formatter to pass `false` fields through to synthetics service. https://github.com/elastic/uptime/issues/424 --- .../synthetics_service/formatters/common.ts | 16 +- .../formatters/format_configs.test.ts | 259 ++++++++++-------- .../formatters/format_configs.ts | 11 +- 3 files changed, 162 insertions(+), 124 deletions(-) diff --git a/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/common.ts b/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/common.ts index 5de7d0e027f41..c70d3d5a4a87b 100644 --- a/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/common.ts +++ b/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/common.ts @@ -5,17 +5,11 @@ * 2.0. */ -import { - CommonFields, - ConfigKey, - MonitorFields, -} from '../../../../common/runtime_types/monitor_management'; - -export type Formatter = - | null - | (( - fields: Partial - ) => boolean | string | string[] | Record | null); +import { CommonFields, ConfigKey, MonitorFields } from '../../../../common/runtime_types'; + +export type FormattedValue = boolean | string | string[] | Record | null; + +export type Formatter = null | ((fields: Partial) => FormattedValue); export type CommonFormatMap = Record; diff --git a/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/format_configs.test.ts b/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/format_configs.test.ts index 5f3a397134c53..afb12ae505957 100644 --- a/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/format_configs.test.ts +++ b/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/format_configs.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { FormattedValue } from './common'; import { formatMonitorConfig } from './format_configs'; import { ConfigKey, @@ -13,127 +14,169 @@ import { MonitorFields, ResponseBodyIndexPolicy, ScheduleUnit, -} from '../../../../common/runtime_types/monitor_management'; +} from '../../../../common/runtime_types'; describe('formatMonitorConfig', () => { - const testHTTPConfig: Partial = { - type: 'http' as DataStream, - enabled: true, - schedule: { number: '3', unit: 'm' as ScheduleUnit }, - 'service.name': '', - tags: [], - timeout: '16', - name: 'Test', - locations: [], - __ui: { is_tls_enabled: false, is_zip_url_tls_enabled: false }, - urls: 'https://www.google.com', - max_redirects: '0', - password: '3z9SBOQWW5F0UrdqLVFqlF6z', - proxy_url: '', - 'check.response.body.negative': [], - 'check.response.body.positive': [], - 'response.include_body': 'on_error' as ResponseBodyIndexPolicy, - 'check.response.headers': {}, - 'response.include_headers': true, - 'check.response.status': [], - 'check.request.body': { type: 'text' as Mode, value: '' }, - 'check.request.headers': {}, - 'check.request.method': 'GET', - username: '', - }; - - it.skip('sets https keys properly', () => { - const yamlConfig = formatMonitorConfig( - Object.keys(testHTTPConfig) as ConfigKey[], - testHTTPConfig - ); - - expect(yamlConfig).toEqual({ - 'check.request.method': 'GET', + describe('http fields', () => { + const testHTTPConfig: Partial = { + type: 'http' as DataStream, enabled: true, + schedule: { number: '3', unit: 'm' as ScheduleUnit }, + 'service.name': '', + tags: [], + timeout: '16', + name: 'Test', locations: [], + __ui: { is_tls_enabled: false, is_zip_url_tls_enabled: false }, + urls: 'https://www.google.com', max_redirects: '0', - name: 'Test', password: '3z9SBOQWW5F0UrdqLVFqlF6z', - 'response.include_body': 'on_error', + proxy_url: '', + 'check.response.body.negative': [], + 'check.response.body.positive': [], + 'response.include_body': 'on_error' as ResponseBodyIndexPolicy, + 'check.response.headers': {}, 'response.include_headers': true, - schedule: '@every 3m', - timeout: '16s', - type: 'http', - urls: 'https://www.google.com', + 'check.response.status': [], + 'check.request.body': { type: 'text' as Mode, value: '' }, + 'check.request.headers': {}, + 'check.request.method': 'GET', + username: '', + }; + + it('sets https keys properly', () => { + const yamlConfig = formatMonitorConfig( + Object.keys(testHTTPConfig) as ConfigKey[], + testHTTPConfig + ); + + expect(yamlConfig).toEqual({ + 'check.request.method': 'GET', + enabled: true, + locations: [], + max_redirects: '0', + name: 'Test', + password: '3z9SBOQWW5F0UrdqLVFqlF6z', + 'response.include_body': 'on_error', + 'response.include_headers': true, + schedule: '@every 3m', + timeout: '16s', + type: 'http', + urls: 'https://www.google.com', + }); }); }); - const testBrowserConfig = { - type: 'browser', - enabled: true, - schedule: { number: '3', unit: 'm' }, - 'service.name': '', - tags: [], - timeout: '16', - name: 'Test', - locations: [], - __ui: { - script_source: { is_generated_script: false, file_name: '' }, - is_zip_url_tls_enabled: false, - is_tls_enabled: false, - }, - 'source.zip_url.url': '', - 'source.zip_url.username': '', - 'source.zip_url.password': '', - 'source.zip_url.folder': '', - 'source.zip_url.proxy_url': '', - 'source.inline.script': - "step('Go to https://www.google.com/', async () => {\n await page.goto('https://www.google.com/');\n});", - params: '', - screenshots: 'on', - synthetics_args: [], - 'filter_journeys.match': '', - 'filter_journeys.tags': ['dev'], - ignore_https_errors: false, - 'throttling.is_enabled': true, - 'throttling.download_speed': '5', - 'throttling.upload_speed': '3', - 'throttling.latency': '20', - 'throttling.config': '5d/3u/20l', - } as Partial; - - it('sets browser keys properly', () => { - const yamlConfig = formatMonitorConfig( - Object.keys(testBrowserConfig) as ConfigKey[], - testBrowserConfig - ); - - expect(yamlConfig).toEqual({ - enabled: true, - 'filter_journeys.tags': ['dev'], - locations: [], - name: 'Test', - schedule: '@every 3m', - screenshots: 'on', - 'source.inline.script': - "step('Go to https://www.google.com/', async () => {\n await page.goto('https://www.google.com/');\n});", - throttling: '5d/3u/20l', - timeout: '16s', - type: 'browser', + describe('browser fields', () => { + let testBrowserConfig: Partial; + let formattedBrowserConfig: Record; + + beforeEach(() => { + testBrowserConfig = { + type: DataStream.BROWSER, + enabled: true, + schedule: { number: '3', unit: ScheduleUnit.MINUTES }, + 'service.name': '', + tags: [], + timeout: '16', + name: 'Test', + locations: [], + __ui: { + script_source: { is_generated_script: false, file_name: '' }, + is_zip_url_tls_enabled: false, + is_tls_enabled: false, + }, + 'source.zip_url.url': '', + 'source.zip_url.username': '', + 'source.zip_url.password': '', + 'source.zip_url.folder': '', + 'source.zip_url.proxy_url': '', + 'source.inline.script': + "step('Go to https://www.google.com/', async () => {\n await page.goto('https://www.google.com/');\n});", + params: '', + screenshots: 'on', + synthetics_args: [], + 'filter_journeys.match': '', + 'filter_journeys.tags': ['dev'], + ignore_https_errors: false, + 'throttling.is_enabled': true, + 'throttling.download_speed': '5', + 'throttling.upload_speed': '3', + 'throttling.latency': '20', + 'throttling.config': '5d/3u/20l', + }; + + formattedBrowserConfig = { + enabled: true, + 'filter_journeys.tags': ['dev'], + ignore_https_errors: false, + locations: [], + name: 'Test', + schedule: '@every 3m', + screenshots: 'on', + 'source.inline.script': + "step('Go to https://www.google.com/', async () => {\n await page.goto('https://www.google.com/');\n});", + throttling: '5d/3u/20l', + timeout: '16s', + type: 'browser', + }; }); - testBrowserConfig['throttling.is_enabled'] = false; - testBrowserConfig['filter_journeys.tags'] = []; + it('sets browser keys properly', () => { + const yamlConfig = formatMonitorConfig( + Object.keys(testBrowserConfig) as ConfigKey[], + testBrowserConfig + ); - expect( - formatMonitorConfig(Object.keys(testBrowserConfig) as ConfigKey[], testBrowserConfig) - ).toEqual({ - enabled: true, - locations: [], - name: 'Test', - schedule: '@every 3m', - screenshots: 'on', - 'source.inline.script': - "step('Go to https://www.google.com/', async () => {\n await page.goto('https://www.google.com/');\n});", - throttling: false, - timeout: '16s', - type: 'browser', + expect(yamlConfig).toEqual(formattedBrowserConfig); + }); + + it('excludes UI fields', () => { + testBrowserConfig['throttling.is_enabled'] = false; + testBrowserConfig['throttling.upload_speed'] = '3'; + + const formattedConfig = formatMonitorConfig( + Object.keys(testBrowserConfig) as ConfigKey[], + testBrowserConfig + ); + + const expected = { + ...formattedConfig, + throttling: false, + 'throttling.is_enabled': undefined, + 'throttling.upload_speed': undefined, + }; + + expect(formattedConfig).toEqual(expected); + }); + + it('excludes empty array values', () => { + testBrowserConfig['filter_journeys.tags'] = []; + + const formattedConfig = formatMonitorConfig( + Object.keys(testBrowserConfig) as ConfigKey[], + testBrowserConfig + ); + + const expected = { + ...formattedConfig, + 'filter_journeys.tags': undefined, + }; + + expect(formattedConfig).toEqual(expected); + }); + + it('does not exclude "false" fields', () => { + testBrowserConfig.enabled = false; + + const formattedConfig = formatMonitorConfig( + Object.keys(testBrowserConfig) as ConfigKey[], + testBrowserConfig + ); + + const expected = { ...formattedConfig, enabled: false }; + + expect(formattedConfig).toEqual(expected); }); }); }); diff --git a/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/format_configs.ts b/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/format_configs.ts index 4eba1a57d88db..5743d05429799 100644 --- a/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/format_configs.ts +++ b/x-pack/plugins/uptime/server/lib/synthetics_service/formatters/format_configs.ts @@ -6,7 +6,7 @@ */ import { isNil, omitBy } from 'lodash'; -import { ConfigKey, MonitorFields } from '../../../../common/runtime_types/monitor_management'; +import { ConfigKey, MonitorFields } from '../../../../common/runtime_types'; import { formatters } from './index'; const UI_KEYS_TO_SKIP = [ @@ -29,11 +29,12 @@ export const formatMonitorConfig = (configKeys: ConfigKey[], config: Partial { if (!UI_KEYS_TO_SKIP.includes(key)) { const value = config[key] ?? null; - if (value && formatters[key]) { - formattedMonitor[key] = formatters[key]?.(config); - } else if (value) { - formattedMonitor[key] = value; + + if (value === null || value === '') { + return; } + + formattedMonitor[key] = !!formatters[key] ? formatters[key]?.(config) : value; } });