[Synthetics] Quote monitor name to prevent invalid yaml (#157453)

## Summary

Appropriately quotes monitor names for synthetics integration policies,
to ensure that customers can use monitor names that would otherwise
break yaml.

### Testing
1. Create a private location
2. Save a monitor with name `[Synthetics] test` to that private location
3. Navigate to the agent policy for that location. Confirm that the
integration policy was added to the agent policy, and that the name is
correct

---------

Co-authored-by: Dominique Clarke <dominique.clarke@elastic.co>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Shahzad 2023-06-02 20:43:40 +02:00 committed by GitHub
parent 380618622d
commit d8cdd4ae48
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 504 additions and 300 deletions

View file

@ -0,0 +1,13 @@
/*
* 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.
*/
/* Formats kibana space id into a valid Fleet-compliant data-stream namespace */
import { INVALID_NAMESPACE_CHARACTERS } from '@kbn/fleet-plugin/common';
export const formatKibanaNamespace = (spaceId: string) => {
const namespaceRegExp = new RegExp(INVALID_NAMESPACE_CHARACTERS, 'g');
return spaceId.replace(namespaceRegExp, '_');
};

View file

@ -1,28 +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 { INVALID_NAMESPACE_CHARACTERS } from '@kbn/fleet-plugin/common';
import { HTTPFormatMap, httpFormatters } from './http/formatters';
import { TCPFormatMap, tcpFormatters } from './tcp/formatters';
import { ICMPFormatMap, icmpFormatters } from './icmp/formatters';
import { BrowserFormatMap, browserFormatters } from './browser/formatters';
import { CommonFormatMap, commonFormatters } from './common/formatters';
type Formatters = HTTPFormatMap & TCPFormatMap & ICMPFormatMap & BrowserFormatMap & CommonFormatMap;
export const syntheticsPolicyFormatters: Formatters = {
...httpFormatters,
...icmpFormatters,
...tcpFormatters,
...browserFormatters,
...commonFormatters,
};
/* Formats kibana space id into a valid Fleet-compliant datastream namespace */
export const formatKibanaNamespace = (spaceId: string) => {
const namespaceRegExp = new RegExp(INVALID_NAMESPACE_CHARACTERS, 'g');
return spaceId.replace(namespaceRegExp, '_');
};

View file

@ -5,4 +5,4 @@
* 2.0.
*/
export * from './formatters';
export { formatKibanaNamespace } from './format_space_name';

View file

@ -6,6 +6,7 @@
*/
import { formatKibanaNamespace } from '../../../../../../common/formatters';
import { DEFAULT_FIELDS } from '../constants';
import {
ConfigKey,
DataStream,

View file

@ -15,6 +15,7 @@ import {
import { isValidNamespace } from '@kbn/fleet-plugin/common';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
import { formatKibanaNamespace } from '../../synthetics_service/formatters/private_formatters';
import { getSyntheticsPrivateLocations } from '../../legacy_uptime/lib/saved_objects/private_locations';
import {
ConfigKey,
@ -23,7 +24,6 @@ import {
EncryptedSyntheticsMonitor,
PrivateLocation,
} from '../../../common/runtime_types';
import { formatKibanaNamespace } from '../../../common/formatters';
import { RouteContext, SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types';
import { API_URLS } from '../../../common/constants';
import {

View file

@ -5,29 +5,13 @@
* 2.0.
*/
import { arrayFormatter, stringToObjectFormatter } from './formatting_utils';
import { commonFormatters as commonBasicFormatters } from '../../../common/formatters/common/formatters';
import { CommonFields, ConfigKey, MonitorFields } from '../../../common/runtime_types';
import { ConfigKey } from '../../../common/constants/monitor_management';
export type FormattedValue =
| boolean
| number
| string
| string[]
| Record<string, unknown>
| null
| Function;
export type Formatter =
| null
| ((fields: Partial<MonitorFields>, key: ConfigKey) => FormattedValue)
| Function;
export type CommonFormatMap = Record<keyof CommonFields, Formatter>;
export const commonFormatters: CommonFormatMap = {
...commonBasicFormatters,
[ConfigKey.PARAMS]: stringToObjectFormatter,
[ConfigKey.SCHEDULE]: (fields) =>
`@every ${fields[ConfigKey.SCHEDULE]?.number}${fields[ConfigKey.SCHEDULE]?.unit}`,
[ConfigKey.TAGS]: arrayFormatter,
};
export const PARAMS_KEYS_TO_SKIP = [
'secrets',
'fields',
ConfigKey.LOCATIONS,
ConfigKey.TLS_VERSION,
ConfigKey.SOURCE_PROJECT_CONTENT,
ConfigKey.SOURCE_INLINE,
];

View file

@ -5,31 +5,43 @@
* 2.0.
*/
import { Logger } from '@kbn/logging';
import { ConfigKey, MonitorFields } from '../../../common/runtime_types';
import { ParsedVars, replaceVarsWithParams } from './lightweight_param_formatter';
import variableParser from './variable_parser';
type FormatterFn = (
fields: Partial<MonitorFields>,
key: ConfigKey
) => string | null | Record<string, any> | string[];
export type FormatterFn = (fields: Partial<MonitorFields>, key: ConfigKey) => string | null;
export const arrayFormatter: FormatterFn = (fields, key) => {
const value = (fields[key] as string[]) ?? [];
return value.length ? value : null;
};
export const objectFormatter: FormatterFn = (fields, key) => {
const value = (fields[key] as Record<string, any>) ?? {};
return Object.keys(value).length ? value : null;
};
export const stringToObjectFormatter: FormatterFn = (fields, key) => {
const value = fields[key] as string;
try {
const obj = JSON.parse(value || '{}');
return Object.keys(obj).length ? obj : undefined;
} catch {
return undefined;
export const replaceStringWithParams = (
value: string | boolean | {} | [],
params: Record<string, string>,
logger?: Logger
) => {
if (!value || typeof value === 'boolean') {
return value as string | null;
}
try {
if (typeof value !== 'string') {
const strValue = JSON.stringify(value);
const parsedVars: ParsedVars = variableParser.parse(strValue);
const parseValue = replaceVarsWithParams(parsedVars, params);
return JSON.parse(parseValue);
}
const parsedVars: ParsedVars = variableParser.parse(value);
return replaceVarsWithParams(parsedVars, params);
} catch (e) {
logger?.error(`error parsing vars for value ${JSON.stringify(value)}, ${e}`);
}
return value as string | null;
};
export const secondsToCronFormatter: FormatterFn = (fields, key) => {
const value = (fields[key] as string) ?? '';
return value ? `${value}s` : null;
};

View file

@ -1,16 +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 { icmpFormatters as basicICMPFormatters } from '../../../common/formatters/icmp/formatters';
import { Formatter, commonFormatters } from './common';
import { ICMPFields } from '../../../common/runtime_types/monitor_management';
export type ICMPFormatMap = Record<keyof ICMPFields, Formatter>;
export const icmpFormatters: ICMPFormatMap = {
...commonFormatters,
...basicICMPFormatters,
};

View file

@ -4,9 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { ConfigKey } from '../../runtime_types';
import { throttlingFormatter } from './formatters';
import { ConfigKey } from '../../../../common/runtime_types';
import { throttlingFormatter } from './browser_formatters';
describe('formatters', () => {
describe('throttling formatter', () => {

View file

@ -4,17 +4,17 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { BrowserFields, ConfigKey } from '../../runtime_types/monitor_management';
import { Formatter, commonFormatters } from '../common/formatters';
import { DEFAULT_THROTTLING_VALUE } from '../../../../common/constants/monitor_defaults';
import { Formatter, commonFormatters } from './common_formatters';
import {
arrayToJsonFormatter,
objectToJsonFormatter,
stringToJsonFormatter,
} from '../formatting_utils';
import { DEFAULT_THROTTLING_VALUE } from '../../constants/monitor_defaults';
} from './formatting_utils';
import { tlsFormatters } from '../tls/formatters';
import { tlsFormatters } from './tls_formatters';
import { BrowserFields, ConfigKey } from '../../../../common/runtime_types';
export type BrowserFormatMap = Record<keyof BrowserFields, Formatter>;
@ -37,9 +37,9 @@ export const browserFormatters: BrowserFormatMap = {
[ConfigKey.SCREENSHOTS]: null,
[ConfigKey.IGNORE_HTTPS_ERRORS]: null,
[ConfigKey.PLAYWRIGHT_OPTIONS]: null,
[ConfigKey.TEXT_ASSERTION]: null,
[ConfigKey.PORT]: null,
[ConfigKey.URLS]: null,
[ConfigKey.TEXT_ASSERTION]: stringToJsonFormatter,
[ConfigKey.PORT]: stringToJsonFormatter,
[ConfigKey.URLS]: stringToJsonFormatter,
[ConfigKey.METADATA]: objectToJsonFormatter,
[ConfigKey.SOURCE_INLINE]: stringToJsonFormatter,
[ConfigKey.SYNTHETICS_ARGS]: arrayToJsonFormatter,

View file

@ -5,13 +5,13 @@
* 2.0.
*/
import { ConfigKey } from '../../runtime_types';
import { ConfigKey } from '../../../../common/runtime_types';
import {
secondsToCronFormatter,
arrayToJsonFormatter,
objectToJsonFormatter,
stringToJsonFormatter,
} from '../formatting_utils';
} from './formatting_utils';
describe('formatters', () => {
describe('cronToSecondsNormalizer', () => {

View file

@ -5,16 +5,21 @@
* 2.0.
*/
import { CommonFields, ConfigKey, SourceType } from '../../runtime_types/monitor_management';
import { arrayToJsonFormatter, FormatterFn } from '../formatting_utils';
import { CommonFields, ConfigKey, SourceType } from '../../../../common/runtime_types';
import {
arrayToJsonFormatter,
stringToJsonFormatter,
FormatterFn,
secondsToCronFormatter,
} from './formatting_utils';
export type Formatter = null | FormatterFn;
export type CommonFormatMap = Record<keyof CommonFields | ConfigKey.NAME, Formatter>;
export const commonFormatters: CommonFormatMap = {
[ConfigKey.APM_SERVICE_NAME]: null,
[ConfigKey.NAME]: null,
[ConfigKey.APM_SERVICE_NAME]: stringToJsonFormatter,
[ConfigKey.NAME]: stringToJsonFormatter,
[ConfigKey.LOCATIONS]: null,
[ConfigKey.MONITOR_TYPE]: null,
[ConfigKey.ENABLED]: null,
@ -24,21 +29,19 @@ export const commonFormatters: CommonFormatMap = {
[ConfigKey.REVISION]: null,
[ConfigKey.MONITOR_SOURCE_TYPE]: null,
[ConfigKey.FORM_MONITOR_TYPE]: null,
[ConfigKey.JOURNEY_ID]: null,
[ConfigKey.PROJECT_ID]: null,
[ConfigKey.CUSTOM_HEARTBEAT_ID]: null,
[ConfigKey.ORIGINAL_SPACE]: null,
[ConfigKey.JOURNEY_ID]: stringToJsonFormatter,
[ConfigKey.PROJECT_ID]: stringToJsonFormatter,
[ConfigKey.CUSTOM_HEARTBEAT_ID]: stringToJsonFormatter,
[ConfigKey.ORIGINAL_SPACE]: stringToJsonFormatter,
[ConfigKey.CONFIG_HASH]: null,
[ConfigKey.MONITOR_QUERY_ID]: null,
[ConfigKey.MONITOR_QUERY_ID]: stringToJsonFormatter,
[ConfigKey.PARAMS]: null,
[ConfigKey.SCHEDULE]: (fields) =>
JSON.stringify(
`@every ${fields[ConfigKey.SCHEDULE]?.number}${fields[ConfigKey.SCHEDULE]?.unit}`
),
[ConfigKey.TAGS]: arrayToJsonFormatter,
[ConfigKey.TIMEOUT]: (fields) => secondsToCronFormatter(fields[ConfigKey.TIMEOUT] || undefined),
[ConfigKey.TIMEOUT]: secondsToCronFormatter,
[ConfigKey.MONITOR_SOURCE_TYPE]: (fields) =>
fields[ConfigKey.MONITOR_SOURCE_TYPE] || SourceType.UI,
};
export const secondsToCronFormatter = (value: string = '') => (value ? `${value}s` : null);

View file

@ -4,9 +4,9 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { ConfigKey, DataStream } from '../runtime_types';
import { ConfigKey, DataStream } from '../../../../common/runtime_types';
import { formatSyntheticsPolicy } from './format_synthetics_policy';
import { PROFILE_VALUES_ENUM, PROFILES_MAP } from '../constants/monitor_defaults';
import { PROFILE_VALUES_ENUM, PROFILES_MAP } from '../../../../common/constants/monitor_defaults';
const gParams = { proxyUrl: 'https://proxy.com' };
describe('formatSyntheticsPolicy', () => {
@ -354,7 +354,7 @@ describe('formatSyntheticsPolicy', () => {
},
id: {
type: 'text',
value: '00bb3ceb-a242-4c7a-8405-8da963661374',
value: '"00bb3ceb-a242-4c7a-8405-8da963661374"',
},
ignore_https_errors: {
type: 'bool',
@ -372,7 +372,7 @@ describe('formatSyntheticsPolicy', () => {
},
name: {
type: 'text',
value: 'Test HTTP Monitor 03',
value: '"Test HTTP Monitor 03"',
},
origin: {
type: 'text',
@ -401,7 +401,7 @@ describe('formatSyntheticsPolicy', () => {
},
'service.name': {
type: 'text',
value: '',
value: '"Local Service"',
},
'source.inline.script': {
type: 'yaml',
@ -532,7 +532,7 @@ describe('formatSyntheticsPolicy', () => {
},
id: {
type: 'text',
value: '51ccd9d9-fc3f-4718-ba9d-b6ef80e73fc5',
value: '"51ccd9d9-fc3f-4718-ba9d-b6ef80e73fc5"',
},
location_name: {
type: 'text',
@ -550,7 +550,7 @@ describe('formatSyntheticsPolicy', () => {
},
name: {
type: 'text',
value: 'Test Monitor',
value: '"Test Monitor"',
},
origin: {
type: 'text',
@ -558,11 +558,11 @@ describe('formatSyntheticsPolicy', () => {
},
password: {
type: 'password',
value: 'changeme',
value: '"changeme"',
},
proxy_url: {
type: 'text',
value: 'https://proxy.com',
value: '"https://proxy.com"',
},
'response.include_body': {
type: 'text',
@ -582,7 +582,7 @@ describe('formatSyntheticsPolicy', () => {
},
'service.name': {
type: 'text',
value: 'LocalService',
value: '"LocalService"',
},
'ssl.certificate': {
type: 'yaml',
@ -622,11 +622,11 @@ describe('formatSyntheticsPolicy', () => {
},
urls: {
type: 'text',
value: 'https://www.google.com',
value: '"https://www.google.com"',
},
username: {
type: 'text',
value: '',
value: '"admin"',
},
},
},
@ -1110,7 +1110,7 @@ const browserConfig: any = {
enabled: true,
alert: { status: { enabled: true } },
schedule: { number: '3', unit: 'm' },
'service.name': '',
'service.name': 'Local Service',
config_id: '00bb3ceb-a242-4c7a-8405-8da963661374',
tags: ['cookie-test', 'browser'],
timeout: '16',
@ -1198,7 +1198,7 @@ const httpPolicy: any = {
'check.request.body': { type: 'text', value: '' },
'check.request.headers': {},
'check.request.method': 'GET',
username: '',
username: 'admin',
'ssl.certificate_authorities': '',
'ssl.certificate': '',
'ssl.key': '',

View file

@ -7,20 +7,12 @@
import { NewPackagePolicy } from '@kbn/fleet-plugin/common';
import { cloneDeep } from 'lodash';
import { throttlingFormatter } from './browser/formatters';
import { LegacyConfigKey } from '../constants/monitor_management';
import { replaceStringWithParams } from './formatting_utils';
import { LegacyConfigKey } from '../../../../common/constants/monitor_management';
import { ConfigKey, DataStream, MonitorFields } from '../../../../common/runtime_types';
import { throttlingFormatter } from './browser_formatters';
import { replaceStringWithParams } from '../formatting_utils';
import { syntheticsPolicyFormatters } from './formatters';
import { ConfigKey, DataStream, MonitorFields } from '../runtime_types';
export const PARAMS_KEYS_TO_SKIP = [
'secrets',
'fields',
ConfigKey.LOCATIONS,
ConfigKey.TLS_VERSION,
ConfigKey.SOURCE_PROJECT_CONTENT,
ConfigKey.SOURCE_INLINE,
];
import { PARAMS_KEYS_TO_SKIP } from '../common';
export const formatSyntheticsPolicy = (
newPolicy: NewPackagePolicy,

View file

@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { formatKibanaNamespace } from './formatters';
import { formatKibanaNamespace } from '../../../../common/formatters/format_space_name';
describe('formatKibanaNamespace', () => {
it('replaces all invalid characters with an underscore', () => {

View file

@ -0,0 +1,21 @@
/*
* 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 { HTTPFormatMap, httpFormatters } from './http_formatters';
import { TCPFormatMap, tcpFormatters } from './tcp_formatters';
import { ICMPFormatMap, icmpFormatters } from './icmp_formatters';
import { BrowserFormatMap, browserFormatters } from './browser_formatters';
import { CommonFormatMap, commonFormatters } from './common_formatters';
type Formatters = HTTPFormatMap & TCPFormatMap & ICMPFormatMap & BrowserFormatMap & CommonFormatMap;
export const syntheticsPolicyFormatters: Formatters = {
...httpFormatters,
...icmpFormatters,
...tcpFormatters,
...browserFormatters,
...commonFormatters,
};

View file

@ -5,10 +5,7 @@
* 2.0.
*/
import { Logger } from '@kbn/logging';
import { replaceVarsWithParams, ParsedVars } from './lightweight_param_formatter';
import variableParser from './variable_parser';
import { ConfigKey, MonitorFields } from '../runtime_types';
import { ConfigKey, MonitorFields } from '../../../../common/runtime_types';
export type FormatterFn = (fields: Partial<MonitorFields>, key: ConfigKey) => string | null;
@ -61,32 +58,13 @@ export const stringToJsonFormatter: FormatterFn = (fields, key) => {
return value ? JSON.stringify(value) : null;
};
export const replaceStringWithParams = (
value: string | boolean | {} | [],
params: Record<string, string>,
logger?: Logger
) => {
if (!value || typeof value === 'boolean') {
return value as string | null;
}
export const stringifyString = (value?: string) => {
if (!value) return value;
try {
if (typeof value !== 'string') {
const strValue = JSON.stringify(value);
const parsedVars: ParsedVars = variableParser.parse(strValue);
const parseValue = replaceVarsWithParams(parsedVars, params);
return JSON.parse(parseValue);
}
const parsedVars: ParsedVars = variableParser.parse(value);
return replaceVarsWithParams(parsedVars, params);
return JSON.stringify(value);
} catch (e) {
logger?.error(`error parsing vars for value ${JSON.stringify(value)}, ${e}`);
return value;
}
return value as string | null;
};
export const secondsToCronFormatter: FormatterFn = (fields, key) => {

View file

@ -5,26 +5,32 @@
* 2.0.
*/
import { tlsFormatters } from '../tls/formatters';
import { HTTPFields, ConfigKey } from '../../runtime_types/monitor_management';
import { ConfigKey, HTTPFields } from '../../../../common/runtime_types';
import { tlsFormatters } from './tls_formatters';
import { Formatter, commonFormatters } from '../common/formatters';
import { arrayToJsonFormatter, objectToJsonFormatter } from '../formatting_utils';
import { Formatter, commonFormatters } from './common_formatters';
import {
stringToJsonFormatter,
arrayToJsonFormatter,
objectToJsonFormatter,
} from './formatting_utils';
export type HTTPFormatMap = Record<keyof HTTPFields, Formatter>;
export const httpFormatters: HTTPFormatMap = {
...commonFormatters,
...tlsFormatters,
[ConfigKey.MAX_REDIRECTS]: null,
[ConfigKey.REQUEST_METHOD_CHECK]: null,
[ConfigKey.RESPONSE_BODY_INDEX]: null,
[ConfigKey.RESPONSE_HEADERS_INDEX]: null,
[ConfigKey.METADATA]: objectToJsonFormatter,
[ConfigKey.URLS]: null,
[ConfigKey.USERNAME]: null,
[ConfigKey.PASSWORD]: null,
[ConfigKey.PROXY_URL]: null,
[ConfigKey.URLS]: stringToJsonFormatter,
[ConfigKey.USERNAME]: stringToJsonFormatter,
[ConfigKey.PASSWORD]: stringToJsonFormatter,
[ConfigKey.PROXY_URL]: stringToJsonFormatter,
[ConfigKey.PROXY_HEADERS]: objectToJsonFormatter,
[ConfigKey.PORT]: null,
[ConfigKey.PORT]: stringToJsonFormatter,
[ConfigKey.RESPONSE_BODY_CHECK_NEGATIVE]: arrayToJsonFormatter,
[ConfigKey.RESPONSE_BODY_CHECK_POSITIVE]: arrayToJsonFormatter,
[ConfigKey.RESPONSE_JSON_CHECK]: arrayToJsonFormatter,
@ -39,6 +45,4 @@ export const httpFormatters: HTTPFormatMap = {
[ConfigKey.MODE]: null,
[ConfigKey.IPV4]: null,
[ConfigKey.IPV6]: null,
...tlsFormatters,
...commonFormatters,
};

View file

@ -0,0 +1,23 @@
/*
* 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 { ConfigKey, ICMPFields } from '../../../../common/runtime_types';
import { secondsToCronFormatter } from './formatting_utils';
import { Formatter, commonFormatters } from './common_formatters';
import { stringToJsonFormatter } from './formatting_utils';
export type ICMPFormatMap = Record<keyof ICMPFields, Formatter>;
export const icmpFormatters: ICMPFormatMap = {
...commonFormatters,
[ConfigKey.HOSTS]: stringToJsonFormatter,
[ConfigKey.WAIT]: secondsToCronFormatter,
[ConfigKey.MODE]: null,
[ConfigKey.IPV4]: null,
[ConfigKey.IPV6]: null,
};

View file

@ -0,0 +1,9 @@
/*
* 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.
*/
export * from './formatters';
export { formatKibanaNamespace } from '../../../../common/formatters/format_space_name';

View file

@ -0,0 +1,30 @@
/*
* 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 { ConfigKey, TCPFields } from '../../../../common/runtime_types';
import { objectToJsonFormatter } from './formatting_utils';
import { tlsFormatters } from './tls_formatters';
import { stringToJsonFormatter } from './formatting_utils';
import { commonFormatters, Formatter } from './common_formatters';
export type TCPFormatMap = Record<keyof TCPFields, Formatter>;
export const tcpFormatters: TCPFormatMap = {
...commonFormatters,
...tlsFormatters,
[ConfigKey.METADATA]: objectToJsonFormatter,
[ConfigKey.HOSTS]: stringToJsonFormatter,
[ConfigKey.PROXY_USE_LOCAL_RESOLVER]: null,
[ConfigKey.RESPONSE_RECEIVE_CHECK]: stringToJsonFormatter,
[ConfigKey.REQUEST_SEND_CHECK]: stringToJsonFormatter,
[ConfigKey.PROXY_URL]: stringToJsonFormatter,
[ConfigKey.PORT]: stringToJsonFormatter,
[ConfigKey.URLS]: stringToJsonFormatter,
[ConfigKey.MODE]: null,
[ConfigKey.IPV4]: null,
[ConfigKey.IPV6]: null,
};

View file

@ -4,13 +4,13 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { TLSFields, ConfigKey } from '../../runtime_types/monitor_management';
import { ConfigKey, TLSFields } from '../../../../common/runtime_types';
import {
tlsArrayToYamlFormatter,
tlsValueToStringFormatter,
tlsValueToYamlFormatter,
} from '../formatting_utils';
import { Formatter } from '../common/formatters';
} from './formatting_utils';
import { Formatter } from './common_formatters';
type TLSFormatMap = Record<keyof TLSFields, Formatter>;

View file

@ -0,0 +1,70 @@
/*
* 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 { ConfigKey } from '../../../../common/runtime_types';
import { throttlingFormatter } from './browser';
describe('formatters', () => {
describe('throttling formatter', () => {
it('formats for no throttling', () => {
expect(
throttlingFormatter!(
{
[ConfigKey.THROTTLING_CONFIG]: {
value: {
download: '0',
upload: '0',
latency: '0',
},
label: 'No throttling',
id: 'no-throttling',
},
},
ConfigKey.THROTTLING_CONFIG
)
).toEqual(false);
});
it('formats for default throttling', () => {
expect(
throttlingFormatter!(
{
[ConfigKey.THROTTLING_CONFIG]: {
value: {
download: '5',
upload: '3',
latency: '20',
},
label: 'Default',
id: 'default',
},
},
ConfigKey.THROTTLING_CONFIG
)
).toEqual({ download: 5, upload: 3, latency: 20 });
});
it('formats for custom throttling', () => {
expect(
throttlingFormatter!(
{
[ConfigKey.THROTTLING_CONFIG]: {
value: {
download: '1.25',
upload: '0.75',
latency: '150',
},
label: 'Custom',
id: 'custom',
},
},
ConfigKey.THROTTLING_CONFIG
)
).toEqual({ download: 1.25, upload: 0.75, latency: 150 });
});
});
});

View file

@ -5,16 +5,15 @@
* 2.0.
*/
import { browserFormatters as basicBrowserFormatters } from '../../../common/formatters/browser/formatters';
import { DEFAULT_BROWSER_ADVANCED_FIELDS } from '../../../../common/constants/monitor_defaults';
import { BrowserFields, ConfigKey } from '../../../../common/runtime_types';
import { Formatter, commonFormatters } from './common';
import { BrowserFields, ConfigKey } from '../../../common/runtime_types/monitor_management';
import { DEFAULT_BROWSER_ADVANCED_FIELDS } from '../../../common/constants/monitor_defaults';
import { tlsFormatters } from './tls';
import { arrayFormatter, objectFormatter, stringToObjectFormatter } from './formatting_utils';
export type BrowserFormatMap = Record<keyof BrowserFields, Formatter>;
const throttlingFormatter: Formatter = (fields) => {
export const throttlingFormatter: Formatter = (fields) => {
const value = fields[ConfigKey.THROTTLING_CONFIG];
const defaultThrottling = DEFAULT_BROWSER_ADVANCED_FIELDS[ConfigKey.THROTTLING_CONFIG].value;
@ -34,7 +33,14 @@ const throttlingFormatter: Formatter = (fields) => {
};
export const browserFormatters: BrowserFormatMap = {
...basicBrowserFormatters,
...commonFormatters,
...tlsFormatters,
[ConfigKey.SOURCE_PROJECT_CONTENT]: null,
[ConfigKey.SCREENSHOTS]: null,
[ConfigKey.IGNORE_HTTPS_ERRORS]: null,
[ConfigKey.TEXT_ASSERTION]: null,
[ConfigKey.PORT]: null,
[ConfigKey.URLS]: null,
[ConfigKey.METADATA]: objectFormatter,
[ConfigKey.SOURCE_INLINE]: null,
[ConfigKey.THROTTLING_CONFIG]: throttlingFormatter,
@ -42,6 +48,6 @@ export const browserFormatters: BrowserFormatMap = {
[ConfigKey.SYNTHETICS_ARGS]: arrayFormatter,
[ConfigKey.JOURNEY_FILTERS_TAGS]: arrayFormatter,
[ConfigKey.PLAYWRIGHT_OPTIONS]: stringToObjectFormatter,
...commonFormatters,
...tlsFormatters,
[ConfigKey.JOURNEY_FILTERS_TAGS]: arrayFormatter,
[ConfigKey.PLAYWRIGHT_OPTIONS]: stringToObjectFormatter,
};

View file

@ -5,8 +5,9 @@
* 2.0.
*/
import { ConfigKey } from '../../../common/runtime_types';
import { stringToObjectFormatter } from './formatting_utils';
import { ConfigKey } from '../../../../common/runtime_types';
import { secondsToCronFormatter } from '../formatting_utils';
describe('common formatters', () => {
it.each([
@ -18,3 +19,11 @@ describe('common formatters', () => {
expect(stringToObjectFormatter({ name: input }, ConfigKey.NAME)).toEqual(expected);
});
});
describe('formatters', () => {
describe('cronToSecondsNormalizer', () => {
it('takes a number of seconds and converts it to cron format', () => {
expect(secondsToCronFormatter({ [ConfigKey.WAIT]: '3' }, ConfigKey.WAIT)).toEqual('3s');
});
});
});

View file

@ -0,0 +1,56 @@
/*
* 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 { secondsToCronFormatter } from '../formatting_utils';
import { arrayFormatter, stringToObjectFormatter } from './formatting_utils';
import {
CommonFields,
ConfigKey,
MonitorFields,
SourceType,
} from '../../../../common/runtime_types';
export type FormattedValue =
| boolean
| number
| string
| string[]
| Record<string, unknown>
| null
| Function;
export type Formatter =
| null
| ((fields: Partial<MonitorFields>, key: ConfigKey) => FormattedValue)
| Function;
export type CommonFormatMap = Record<keyof CommonFields, Formatter>;
export const commonFormatters: CommonFormatMap = {
[ConfigKey.APM_SERVICE_NAME]: null,
[ConfigKey.NAME]: null,
[ConfigKey.LOCATIONS]: null,
[ConfigKey.MONITOR_TYPE]: null,
[ConfigKey.ENABLED]: null,
[ConfigKey.ALERT_CONFIG]: null,
[ConfigKey.CONFIG_ID]: null,
[ConfigKey.NAMESPACE]: null,
[ConfigKey.REVISION]: null,
[ConfigKey.FORM_MONITOR_TYPE]: null,
[ConfigKey.JOURNEY_ID]: null,
[ConfigKey.PROJECT_ID]: null,
[ConfigKey.CUSTOM_HEARTBEAT_ID]: null,
[ConfigKey.ORIGINAL_SPACE]: null,
[ConfigKey.CONFIG_HASH]: null,
[ConfigKey.MONITOR_QUERY_ID]: null,
[ConfigKey.TIMEOUT]: secondsToCronFormatter,
[ConfigKey.MONITOR_SOURCE_TYPE]: (fields) =>
fields[ConfigKey.MONITOR_SOURCE_TYPE] || SourceType.UI,
[ConfigKey.PARAMS]: stringToObjectFormatter,
[ConfigKey.SCHEDULE]: (fields) =>
`@every ${fields[ConfigKey.SCHEDULE]?.number}${fields[ConfigKey.SCHEDULE]?.unit}`,
[ConfigKey.TAGS]: arrayFormatter,
};

View file

@ -5,8 +5,8 @@
* 2.0.
*/
import { DEFAULT_NAMESPACE_STRING } from '../../../common/constants/monitor_defaults';
import { DataStream, MonitorFields } from '../../../common/runtime_types';
import { DEFAULT_NAMESPACE_STRING } from '../../../../common/constants/monitor_defaults';
import { DataStream, MonitorFields } from '../../../../common/runtime_types';
interface DataStreamConfig {
type: DataStream;

View file

@ -11,6 +11,8 @@ import {
formatHeartbeatRequest,
mixParamsWithGlobalParams,
} from './format_configs';
import { loggerMock } from '@kbn/logging-mocks';
import {
ConfigKey,
DataStream,
@ -20,8 +22,7 @@ import {
ScheduleUnit,
SyntheticsMonitor,
VerificationMode,
} from '../../../common/runtime_types';
import { loggerMock } from '@kbn/logging-mocks';
} from '../../../../common/runtime_types';
const testHTTPConfig: Partial<MonitorFields> = {
type: 'http' as DataStream,
@ -35,6 +36,7 @@ const testHTTPConfig: Partial<MonitorFields> = {
__ui: { is_tls_enabled: false },
urls: 'https://www.google.com',
max_redirects: '0',
'url.port': 900,
password: '3z9SBOQWW5F0UrdqLVFqlF6z',
proxy_url: '${proxyUrl}',
'check.response.body.negative': [],
@ -55,7 +57,7 @@ const testHTTPConfig: Partial<MonitorFields> = {
'check.request.headers': {},
'check.request.method': 'GET',
'ssl.verification_mode': VerificationMode.NONE,
username: '',
username: 'test-username',
params: '{"proxyUrl":"https://www.google.com"}',
};
@ -63,7 +65,7 @@ const testBrowserConfig: Partial<MonitorFields> = {
type: DataStream.BROWSER,
enabled: true,
schedule: { number: '3', unit: ScheduleUnit.MINUTES },
'service.name': '',
'service.name': 'APM Service',
tags: [],
timeout: '16',
name: 'Test',
@ -128,6 +130,8 @@ describe('formatMonitorConfig', () => {
type: 'http',
urls: 'https://www.google.com',
proxy_url: 'https://www.google.com',
username: 'test-username',
'url.port': 900,
});
});
@ -159,6 +163,7 @@ describe('formatMonitorConfig', () => {
locations: [],
max_redirects: '0',
name: 'Test',
username: 'test-username',
password: '3z9SBOQWW5F0UrdqLVFqlF6z',
proxy_url: 'https://www.google.com',
'response.include_body': 'on_error',
@ -166,6 +171,7 @@ describe('formatMonitorConfig', () => {
schedule: '@every 3m',
timeout: '16s',
type: 'http',
'url.port': 900,
urls: 'https://www.google.com',
...(isTLSEnabled ? { 'ssl.verification_mode': 'none' } : {}),
});
@ -187,6 +193,7 @@ describe('browser fields', () => {
locations: [],
schedule: '@every 3m',
screenshots: 'on',
'service.name': 'APM Service',
'source.inline.script':
"step('Go to https://www.google.com/', async () => {\n await page.goto('https://www.google.com/');\n});",
throttling: {

View file

@ -7,17 +7,17 @@
import { isEmpty, isNil, omitBy } from 'lodash';
import { Logger } from '@kbn/logging';
import { PARAMS_KEYS_TO_SKIP } from '../../../common/formatters/format_synthetics_policy';
import { replaceStringWithParams } from '../../../common/formatters/formatting_utils';
import { replaceStringWithParams } from '../formatting_utils';
import { PARAMS_KEYS_TO_SKIP } from '../common';
import {
BrowserFields,
ConfigKey,
HeartbeatConfig,
MonitorFields,
SyntheticsMonitor,
HeartbeatConfig,
TLSFields,
} from '../../../common/runtime_types';
import { formatters } from '.';
} from '../../../../common/runtime_types';
import { publicFormatters } from '.';
const UI_KEYS_TO_SKIP = [
ConfigKey.JOURNEY_ID,
@ -52,8 +52,8 @@ export const formatMonitorConfigFields = (
return;
}
if (!!formatters[key]) {
const formatter = formatters[key];
if (!!publicFormatters[key]) {
const formatter = publicFormatters[key];
if (typeof formatter === 'function') {
formattedMonitor[key] = formatter(config, key);
} else {

View file

@ -0,0 +1,35 @@
/*
* 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 { ConfigKey, MonitorFields } from '../../../../common/runtime_types';
type FormatterFn = (
fields: Partial<MonitorFields>,
key: ConfigKey
) => string | null | Record<string, any> | string[];
export const arrayFormatter: FormatterFn = (fields, key) => {
const value = (fields[key] as string[]) ?? [];
return value.length ? value : null;
};
export const objectFormatter: FormatterFn = (fields, key) => {
const value = (fields[key] as Record<string, any>) ?? {};
return Object.keys(value).length ? value : null;
};
export const stringToObjectFormatter: FormatterFn = (fields, key) => {
const value = fields[key] as string;
try {
const obj = JSON.parse(value || '{}');
return Object.keys(obj).length ? obj : undefined;
} catch {
return undefined;
}
};

View file

@ -5,15 +5,32 @@
* 2.0.
*/
import { httpFormatters as basicHttpFormatters } from '../../../common/formatters/http/formatters';
import { ConfigKey, HTTPFields } from '../../../../common/runtime_types';
import { Formatter, commonFormatters } from './common';
import { tlsFormatters } from './tls';
import { ConfigKey, HTTPFields } from '../../../common/runtime_types/monitor_management';
import { arrayFormatter, objectFormatter } from './formatting_utils';
export type HTTPFormatMap = Record<keyof HTTPFields, Formatter>;
export const httpFormatters: HTTPFormatMap = {
...basicHttpFormatters,
...tlsFormatters,
...commonFormatters,
[ConfigKey.MAX_REDIRECTS]: null,
[ConfigKey.REQUEST_METHOD_CHECK]: null,
[ConfigKey.RESPONSE_BODY_INDEX]: null,
[ConfigKey.RESPONSE_HEADERS_INDEX]: null,
[ConfigKey.URLS]: null,
[ConfigKey.USERNAME]: null,
[ConfigKey.PASSWORD]: null,
[ConfigKey.PROXY_URL]: null,
[ConfigKey.PORT]: null,
[ConfigKey.REQUEST_BODY_CHECK]: (fields) =>
fields[ConfigKey.REQUEST_BODY_CHECK]?.value
? JSON.stringify(fields[ConfigKey.REQUEST_BODY_CHECK]?.value)
: null,
[ConfigKey.RESPONSE_BODY_MAX_BYTES]: null,
[ConfigKey.MODE]: null,
[ConfigKey.IPV4]: null,
[ConfigKey.IPV6]: null,
[ConfigKey.METADATA]: objectFormatter,
[ConfigKey.RESPONSE_BODY_CHECK_NEGATIVE]: arrayFormatter,
[ConfigKey.RESPONSE_BODY_CHECK_POSITIVE]: arrayFormatter,
@ -23,6 +40,4 @@ export const httpFormatters: HTTPFormatMap = {
[ConfigKey.REQUEST_HEADERS_CHECK]: objectFormatter,
[ConfigKey.REQUEST_BODY_CHECK]: (fields) => fields[ConfigKey.REQUEST_BODY_CHECK]?.value || null,
[ConfigKey.PROXY_HEADERS]: objectFormatter,
...tlsFormatters,
...commonFormatters,
};

View file

@ -5,18 +5,16 @@
* 2.0.
*/
import { ConfigKey, ICMPFields } from '../../../../common/runtime_types';
import { secondsToCronFormatter } from '../formatting_utils';
import { ICMPFields, ConfigKey } from '../../runtime_types/monitor_management';
import { Formatter, commonFormatters } from '../common/formatters';
import { Formatter, commonFormatters } from './common';
export type ICMPFormatMap = Record<keyof ICMPFields, Formatter>;
export const icmpFormatters: ICMPFormatMap = {
...commonFormatters,
[ConfigKey.HOSTS]: null,
[ConfigKey.WAIT]: secondsToCronFormatter,
[ConfigKey.MODE]: null,
[ConfigKey.IPV4]: null,
[ConfigKey.IPV6]: null,
...commonFormatters,
};

View file

@ -13,7 +13,7 @@ import { commonFormatters, CommonFormatMap } from './common';
type Formatters = HTTPFormatMap & TCPFormatMap & ICMPFormatMap & BrowserFormatMap & CommonFormatMap;
export const formatters: Formatters = {
export const publicFormatters: Formatters = {
...httpFormatters,
...icmpFormatters,
...tcpFormatters,

View file

@ -5,27 +5,23 @@
* 2.0.
*/
import { TCPFields, ConfigKey } from '../../runtime_types/monitor_management';
import { Formatter, commonFormatters } from '../common/formatters';
import { objectToJsonFormatter } from '../formatting_utils';
import { tlsFormatters } from '../tls/formatters';
import { ConfigKey, TCPFields } from '../../../../common/runtime_types';
import { Formatter, commonFormatters } from './common';
import { tlsFormatters } from './tls';
export type TCPFormatMap = Record<keyof TCPFields, Formatter>;
export const tcpFormatters: TCPFormatMap = {
[ConfigKey.METADATA]: objectToJsonFormatter,
...tlsFormatters,
...commonFormatters,
[ConfigKey.HOSTS]: null,
[ConfigKey.PROXY_USE_LOCAL_RESOLVER]: null,
[ConfigKey.RESPONSE_RECEIVE_CHECK]: null,
[ConfigKey.REQUEST_SEND_CHECK]: null,
[ConfigKey.PROXY_URL]: null,
[ConfigKey.PROXY_URL]: null,
[ConfigKey.PORT]: null,
[ConfigKey.URLS]: null,
[ConfigKey.MODE]: null,
[ConfigKey.IPV4]: null,
[ConfigKey.IPV6]: null,
...tlsFormatters,
...commonFormatters,
[ConfigKey.METADATA]: null,
};

View file

@ -5,9 +5,9 @@
* 2.0.
*/
import { ConfigKey, TLSFields } from '../../../../common/runtime_types';
import { arrayFormatter } from './formatting_utils';
import { Formatter } from './common';
import { ConfigKey, TLSFields } from '../../../common/runtime_types/monitor_management';
type TLSFormatMap = Record<keyof TLSFields, Formatter>;

View file

@ -1,19 +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 { tcpFormatters as baicTCPFormatters } from '../../../common/formatters/tcp/formatters';
import { Formatter, commonFormatters } from './common';
import { tlsFormatters } from './tls';
import { ConfigKey, TCPFields } from '../../../common/runtime_types/monitor_management';
export type TCPFormatMap = Record<keyof TCPFields, Formatter>;
export const tcpFormatters: TCPFormatMap = {
...tlsFormatters,
...commonFormatters,
...baicTCPFormatters,
[ConfigKey.METADATA]: null,
};

View file

@ -7,7 +7,6 @@
import { KibanaRequest, SavedObjectsClientContract } from '@kbn/core/server';
import { loggerMock } from '@kbn/logging-mocks';
import { UptimeServerSetup } from '../../legacy_uptime/lib/adapters';
import { formatSyntheticsPolicy } from '../../../common/formatters/format_synthetics_policy';
import {
DataStream,
MonitorFields,
@ -18,6 +17,7 @@ import {
} from '../../../common/runtime_types';
import { SyntheticsPrivateLocation } from './synthetics_private_location';
import { testMonitorPolicy } from './test_policy';
import { formatSyntheticsPolicy } from '../formatters/private_formatters/format_synthetics_policy';
describe('SyntheticsPrivateLocation', () => {
const mockPrivateLocation: PrivateLocation = {
@ -31,7 +31,7 @@ describe('SyntheticsPrivateLocation', () => {
type: 'http',
enabled: true,
schedule: '@every 3m',
'service.name': '',
'service.name': 'test service',
locations: [mockPrivateLocation],
tags: [],
timeout: '16',
@ -226,7 +226,7 @@ describe('SyntheticsPrivateLocation', () => {
},
name: {
type: 'text',
value: 'Browser monitor',
value: '"Browser monitor"',
},
params: {
type: 'yaml',
@ -246,7 +246,7 @@ describe('SyntheticsPrivateLocation', () => {
},
'service.name': {
type: 'text',
value: '',
value: '"test service"',
},
'source.inline.script': {
type: 'yaml',
@ -286,7 +286,7 @@ const dummyBrowserConfig: Partial<MonitorFields> & {
type: DataStream.BROWSER,
enabled: true,
schedule: { unit: ScheduleUnit.MINUTES, number: '10' },
'service.name': '',
'service.name': 'test service',
tags: [],
timeout: null,
name: 'Browser monitor',

View file

@ -9,7 +9,7 @@ import { NewPackagePolicy } from '@kbn/fleet-plugin/common';
import { NewPackagePolicyWithId } from '@kbn/fleet-plugin/server/services/package_policy';
import { cloneDeep } from 'lodash';
import { SavedObjectError } from '@kbn/core-saved-objects-common';
import { formatSyntheticsPolicy } from '../../../common/formatters/format_synthetics_policy';
import { formatSyntheticsPolicy } from '../formatters/private_formatters/format_synthetics_policy';
import {
ConfigKey,
HeartbeatConfig,
@ -18,6 +18,7 @@ import {
SourceType,
} from '../../../common/runtime_types';
import { UptimeServerSetup } from '../../legacy_uptime/lib/adapters';
import { stringifyString } from '../formatters/private_formatters/formatting_utils';
export interface PrivateConfig {
config: HeartbeatConfig;
@ -86,10 +87,10 @@ export class SyntheticsPrivateLocation {
{
...(config as Partial<MonitorFields>),
config_id: config.fields?.config_id,
location_name: privateLocation.label,
location_name: stringifyString(privateLocation.label),
location_id: privateLocation.id,
'monitor.project.id': config.fields?.['monitor.project.name'],
'monitor.project.name': config.fields?.['monitor.project.name'],
'monitor.project.id': stringifyString(config.fields?.['monitor.project.name']),
'monitor.project.name': stringifyString(config.fields?.['monitor.project.name']),
},
globalParams
);

View file

@ -9,7 +9,6 @@ import { omit } from 'lodash';
import { i18n } from '@kbn/i18n';
import { isValidNamespace } from '@kbn/fleet-plugin/common';
import { formatLocation } from '../../../../common/utils/location_formatter';
import { formatKibanaNamespace } from '../../../../common/formatters';
import {
BrowserFields,
ConfigKey,
@ -23,6 +22,7 @@ import {
} from '../../../../common/runtime_types';
import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults';
import { DEFAULT_COMMON_FIELDS } from '../../../../common/constants/monitor_defaults';
import { formatKibanaNamespace } from '../../formatters/private_formatters';
export interface NormalizedProjectProps {
locations: Locations;

View file

@ -12,10 +12,10 @@ import * as https from 'https';
import { SslConfig } from '@kbn/server-http-tools';
import { Logger } from '@kbn/core/server';
import { LicenseGetLicenseInformation } from '@elastic/elasticsearch/lib/api/types';
import { convertToDataStreamFormat } from './formatters/public_formatters/convert_to_data_stream';
import { UptimeServerSetup } from '../legacy_uptime/lib/adapters';
import { sendErrorTelemetryEvents } from '../routes/telemetry/monitor_upgrade_sender';
import { MonitorFields, PublicLocations, ServiceLocationErrors } from '../../common/runtime_types';
import { convertToDataStreamFormat } from './formatters/convert_to_data_stream';
import { ServiceConfig } from '../../common/config';
const TEST_SERVICE_USERNAME = 'localKibanaIntegrationTestsUser';

View file

@ -20,11 +20,7 @@ import {
SyntheticsPrivateLocation,
} from '../private_location/synthetics_private_location';
import { SyntheticsService } from '../synthetics_service';
import {
ConfigData,
formatHeartbeatRequest,
mixParamsWithGlobalParams,
} from '../formatters/format_configs';
import {
MonitorFields,
SyntheticsMonitorWithId,
@ -34,6 +30,11 @@ import {
SyntheticsMonitorWithSecrets,
MonitorServiceLocation,
} from '../../../common/runtime_types';
import {
ConfigData,
formatHeartbeatRequest,
mixParamsWithGlobalParams,
} from '../formatters/public_formatters/format_configs';
export class SyntheticsMonitorClient {
public syntheticsService: SyntheticsService;

View file

@ -27,12 +27,7 @@ import { getAPIKeyForSyntheticsService } from './get_api_key';
import { getEsHosts } from './get_es_hosts';
import { ServiceConfig } from '../../common/config';
import { ServiceAPIClient, ServiceData } from './service_api_client';
import {
ConfigData,
formatHeartbeatRequest,
formatMonitorConfigFields,
mixParamsWithGlobalParams,
} from './formatters/format_configs';
import {
ConfigKey,
EncryptedSyntheticsMonitor,
@ -47,6 +42,12 @@ import {
import { getServiceLocations } from './get_service_locations';
import { normalizeSecrets } from './utils/secrets';
import {
ConfigData,
formatHeartbeatRequest,
formatMonitorConfigFields,
mixParamsWithGlobalParams,
} from './formatters/public_formatters/format_configs';
const SYNTHETICS_SERVICE_SYNC_MONITORS_TASK_TYPE =
'UPTIME:SyntheticsService:Sync-Saved-Monitor-Objects';

View file

@ -85,7 +85,7 @@ export default function ({ getService }: FtrProviderContext) {
it('does not add a monitor if there is an error in creating integration', async () => {
const newMonitor = { ...httpMonitorJson };
const invalidName = '[] - invalid name';
const invalidName = '!@#$%^&*()_++[\\-\\]- wow';
newMonitor.locations.push({
id: testFleetPolicyID,
@ -104,7 +104,7 @@ export default function ({ getService }: FtrProviderContext) {
expect(apiResponse.body).eql({
statusCode: 500,
message:
'YAMLException: end of the stream or a document separator is expected at line 3, column 10:\n name: [] - invalid name\n ^',
'YAMLException: unknown escape sequence at line 3, column 34:\n name: "!@#$,%,^,&,*,(,),_,+,+,[,\\,\\,-,\\,\\,],-, ,w,o,w,"\n ^',
error: 'Internal Server Error',
});

View file

@ -59,13 +59,13 @@ export default function ({ getService }: FtrProviderContext) {
};
const testMonitors = [
projectMonitors.monitors[0],
{ ...secondMonitor, name: '[] - invalid name' },
{ ...secondMonitor, name: '!@#$%^&*()_++[\\-\\]- wow name' },
];
try {
const body = await monitorTestService.addProjectMonitors(project, testMonitors);
expect(body.createdMonitors.length).eql(1);
expect(body.failedMonitors[0].reason).eql(
'end of the stream or a document separator is expected at line 3, column 10:\n name: [] - invalid name\n ^'
'unknown escape sequence at line 3, column 34:\n name: "!@#$,%,^,&,*,(,),_,+,+,[,\\,\\,-,\\,\\,],-, ,w,o,w, ,n,a,m,e,"\n ^'
);
} finally {
await Promise.all([
@ -92,7 +92,7 @@ export default function ({ getService }: FtrProviderContext) {
expect(editedBody.createdMonitors.length).eql(0);
expect(editedBody.updatedMonitors.length).eql(2);
testMonitors[1].name = '[] - invalid name';
testMonitors[1].name = '!@#$%^&*()_++[\\-\\]- wow name';
const editedBodyError = await monitorTestService.addProjectMonitors(project, testMonitors);
expect(editedBodyError.createdMonitors.length).eql(0);
@ -102,7 +102,7 @@ export default function ({ getService }: FtrProviderContext) {
'Failed to update journey: test-id-2'
);
expect(editedBodyError.failedMonitors[0].reason).eql(
'end of the stream or a document separator is expected at line 3, column 10:\n name: [] - invalid name\n ^'
'unknown escape sequence at line 3, column 34:\n name: "!@#$,%,^,&,*,(,),_,+,+,[,\\,\\,-,\\,\\,],-, ,w,o,w, ,n,a,m,e,"\n ^'
);
} finally {
await Promise.all([

View file

@ -190,17 +190,17 @@ export const getHttpInput = ({
},
enabled: { value: true, type: 'bool' },
type: { value: 'http', type: 'text' },
name: { value: name, type: 'text' },
name: { value: JSON.stringify(name), type: 'text' },
schedule: { value: '"@every 5m"', type: 'text' },
urls: { value: 'https://nextjs-test-synthetics.vercel.app/api/users', type: 'text' },
'service.name': { value: '', type: 'text' },
urls: { value: '"https://nextjs-test-synthetics.vercel.app/api/users"', type: 'text' },
'service.name': { value: null, type: 'text' },
timeout: { value: '3ms', type: 'text' },
max_redirects: { value: '3', type: 'integer' },
proxy_url: { value: proxyUrl ?? 'http://proxy.com', type: 'text' },
proxy_url: { value: proxyUrl ?? '"http://proxy.com"', type: 'text' },
proxy_headers: { value: null, type: 'yaml' },
tags: { value: '["tag1","tag2"]', type: 'yaml' },
username: { value: 'test-username', type: 'text' },
password: { value: 'test', type: 'password' },
username: { value: '"test-username"', type: 'text' },
password: { value: '"test"', type: 'password' },
'response.include_headers': { value: true, type: 'bool' },
'response.include_body': { value: 'never', type: 'text' },
'response.include_body_max_bytes': { value: '1024', type: 'text' },
@ -231,8 +231,11 @@ export const getHttpInput = ({
type: 'text',
value: location.id ?? 'aaa3c150-f94d-11ed-9895-d36d5472fafd',
},
location_name: { value: location.name ?? 'Test private location 0', type: 'text' },
id: { value: id, type: 'text' },
location_name: {
value: JSON.stringify(location.name) ?? '"Test private location 0"',
type: 'text',
},
id: { value: JSON.stringify(id), type: 'text' },
config_id: { value: id, type: 'text' },
run_once: { value: false, type: 'bool' },
origin: { value: projectId ? 'project' : 'ui', type: 'text' },

View file

@ -104,7 +104,7 @@ export const getTestProjectSyntheticsPolicyLightweight = (
},
id: {
type: 'text',
value: id,
value: JSON.stringify(id),
},
ipv4: {
type: 'bool',
@ -120,7 +120,7 @@ export const getTestProjectSyntheticsPolicyLightweight = (
},
location_name: {
type: 'text',
value: 'Test private location 0',
value: '"Test private location 0"',
},
max_redirects: {
type: 'integer',
@ -132,15 +132,15 @@ export const getTestProjectSyntheticsPolicyLightweight = (
},
'monitor.project.id': {
type: 'text',
value: projectId,
value: JSON.stringify(projectId),
},
'monitor.project.name': {
type: 'text',
value: projectId,
value: JSON.stringify(projectId),
},
name: {
type: 'text',
value: name,
value: JSON.stringify(name),
},
origin: {
type: 'text',
@ -148,7 +148,7 @@ export const getTestProjectSyntheticsPolicyLightweight = (
},
password: {
type: 'password',
value: '',
value: null,
},
proxy_headers: {
type: 'yaml',
@ -156,7 +156,7 @@ export const getTestProjectSyntheticsPolicyLightweight = (
},
proxy_url: {
type: 'text',
value: 'testGlobalParamOverwrite',
value: JSON.stringify('testGlobalParamOverwrite'),
},
'response.include_body': {
type: 'text',
@ -180,7 +180,7 @@ export const getTestProjectSyntheticsPolicyLightweight = (
},
'service.name': {
type: 'text',
value: '',
value: null,
},
'ssl.certificate': {
type: 'yaml',
@ -220,11 +220,11 @@ export const getTestProjectSyntheticsPolicyLightweight = (
},
urls: {
type: 'text',
value: 'http://localhost:9200',
value: '"http://localhost:9200"',
},
username: {
type: 'text',
value: '',
value: null,
},
},
compiled_stream: {
@ -701,9 +701,9 @@ export const getTestProjectSyntheticsPolicy = (
},
enabled: { value: true, type: 'bool' },
type: { value: 'browser', type: 'text' },
name: { value: 'check if title is present', type: 'text' },
name: { value: '"check if title is present"', type: 'text' },
schedule: { value: '"@every 10m"', type: 'text' },
'service.name': { value: '', type: 'text' },
'service.name': { value: null, type: 'text' },
timeout: { value: null, type: 'text' },
tags: { value: null, type: 'yaml' },
'source.zip_url.url': { type: 'text' },
@ -747,8 +747,8 @@ export const getTestProjectSyntheticsPolicy = (
config_id: { value: configId, type: 'text' },
run_once: { value: false, type: 'bool' },
origin: { value: 'project', type: 'text' },
'monitor.project.id': { value: projectId, type: 'text' },
'monitor.project.name': { value: projectId, type: 'text' },
'monitor.project.id': { value: JSON.stringify(projectId), type: 'text' },
'monitor.project.name': { value: JSON.stringify(projectId), type: 'text' },
...inputs,
},
id: `synthetics/browser-browser-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,