diff --git a/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/index.tsx b/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/index.tsx index 32846620221ae..16ed53020a313 100644 --- a/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/index.tsx +++ b/x-pack/plugins/fleet/public/components/enrollment_instructions/manual/index.tsx @@ -6,8 +6,10 @@ */ import React from 'react'; + import { useStartServices } from '../../../hooks'; import type { EnrollmentAPIKey } from '../../../types'; + import { PlatformSelector } from './platform_selector'; interface Props { diff --git a/x-pack/plugins/uptime/public/components/fleet_package/contexts/index.ts b/x-pack/plugins/uptime/public/components/fleet_package/contexts/index.ts index df2e9cfa6d4ea..37fdad9b195d4 100644 --- a/x-pack/plugins/uptime/public/components/fleet_package/contexts/index.ts +++ b/x-pack/plugins/uptime/public/components/fleet_package/contexts/index.ts @@ -4,6 +4,16 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { DataStream, PolicyConfig } from '../types'; +import { initialValues as defaultHTTPSimpleFields } from './http_context'; +import { initialValues as defaultHTTPAdvancedFields } from './http_context_advanced'; +import { initialValues as defaultTCPSimpleFields } from './tcp_context'; +import { initialValues as defaultICMPSimpleFields } from './icmp_context'; +import { initialValues as defaultTCPAdvancedFields } from './tcp_context_advanced'; +import { initialValues as defaultBrowserSimpleFields } from './browser_context'; +import { initialValues as defaultBrowserAdvancedFields } from './browser_context_advanced'; +import { initialValues as defaultTLSFields } from './tls_fields_context'; + export { PolicyConfigContext, PolicyConfigContextProvider, @@ -61,3 +71,23 @@ export { export { HTTPContextProvider } from './http_provider'; export { TCPContextProvider } from './tcp_provider'; export { BrowserContextProvider } from './browser_provider'; +export { SyntheticsProviders } from './synthetics_context_providers'; + +export const defaultConfig: PolicyConfig = { + [DataStream.HTTP]: { + ...defaultHTTPSimpleFields, + ...defaultHTTPAdvancedFields, + ...defaultTLSFields, + }, + [DataStream.TCP]: { + ...defaultTCPSimpleFields, + ...defaultTCPAdvancedFields, + ...defaultTLSFields, + }, + [DataStream.ICMP]: defaultICMPSimpleFields, + [DataStream.BROWSER]: { + ...defaultBrowserSimpleFields, + ...defaultBrowserAdvancedFields, + ...defaultTLSFields, + }, +}; diff --git a/x-pack/plugins/uptime/public/components/fleet_package/contexts/policy_config_context.tsx b/x-pack/plugins/uptime/public/components/fleet_package/contexts/policy_config_context.tsx index 69c0e1d7ba4fe..ed183e1f81357 100644 --- a/x-pack/plugins/uptime/public/components/fleet_package/contexts/policy_config_context.tsx +++ b/x-pack/plugins/uptime/public/components/fleet_package/contexts/policy_config_context.tsx @@ -10,6 +10,8 @@ import { DataStream } from '../types'; interface IPolicyConfigContext { setMonitorType: React.Dispatch>; + setName: React.Dispatch>; + setLocations: React.Dispatch>; setIsTLSEnabled: React.Dispatch>; setIsZipUrlTLSEnabled: React.Dispatch>; monitorType: DataStream; @@ -19,6 +21,10 @@ interface IPolicyConfigContext { defaultIsTLSEnabled?: boolean; defaultIsZipUrlTLSEnabled?: boolean; isEditable?: boolean; + defaultName?: string; + name?: string; + defaultLocations?: string[]; + locations?: string[]; } interface IPolicyConfigContextProvider { @@ -26,6 +32,8 @@ interface IPolicyConfigContextProvider { defaultMonitorType?: DataStream; defaultIsTLSEnabled?: boolean; defaultIsZipUrlTLSEnabled?: boolean; + defaultName?: string; + defaultLocations?: string[]; isEditable?: boolean; } @@ -35,6 +43,12 @@ const defaultContext: IPolicyConfigContext = { setMonitorType: (_monitorType: React.SetStateAction) => { throw new Error('setMonitorType was not initialized, set it when you invoke the context'); }, + setName: (_name: React.SetStateAction) => { + throw new Error('setName was not initialized, set it when you invoke the context'); + }, + setLocations: (_locations: React.SetStateAction) => { + throw new Error('setLocations was not initialized, set it when you invoke the context'); + }, setIsTLSEnabled: (_isTLSEnabled: React.SetStateAction) => { throw new Error('setIsTLSEnabled was not initialized, set it when you invoke the context'); }, @@ -47,19 +61,25 @@ const defaultContext: IPolicyConfigContext = { defaultMonitorType: initialValue, // immutable, defaultIsTLSEnabled: false, defaultIsZipUrlTLSEnabled: false, + defaultName: '', + defaultLocations: [], isEditable: false, }; export const PolicyConfigContext = createContext(defaultContext); -export const PolicyConfigContextProvider = ({ +export function PolicyConfigContextProvider({ children, defaultMonitorType = initialValue, defaultIsTLSEnabled = false, defaultIsZipUrlTLSEnabled = false, + defaultName = '', + defaultLocations = [], isEditable = false, -}: IPolicyConfigContextProvider) => { +}: IPolicyConfigContextProvider) { const [monitorType, setMonitorType] = useState(defaultMonitorType); + const [name, setName] = useState(defaultName); + const [locations, setLocations] = useState(defaultLocations); const [isTLSEnabled, setIsTLSEnabled] = useState(defaultIsTLSEnabled); const [isZipUrlTLSEnabled, setIsZipUrlTLSEnabled] = useState(defaultIsZipUrlTLSEnabled); @@ -75,6 +95,12 @@ export const PolicyConfigContextProvider = ({ defaultIsTLSEnabled, defaultIsZipUrlTLSEnabled, isEditable, + defaultName, + name, + setName, + defaultLocations, + locations, + setLocations, }; }, [ monitorType, @@ -84,9 +110,15 @@ export const PolicyConfigContextProvider = ({ defaultIsTLSEnabled, defaultIsZipUrlTLSEnabled, isEditable, + name, + defaultName, + locations, + defaultLocations, ]); return ; -}; +} -export const usePolicyConfigContext = () => useContext(PolicyConfigContext); +export function usePolicyConfigContext() { + return useContext(PolicyConfigContext); +} diff --git a/x-pack/plugins/uptime/public/components/fleet_package/contexts/synthetics_context_providers.tsx b/x-pack/plugins/uptime/public/components/fleet_package/contexts/synthetics_context_providers.tsx new file mode 100644 index 0000000000000..0d730c5f96e97 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/fleet_package/contexts/synthetics_context_providers.tsx @@ -0,0 +1,60 @@ +/* + * 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 React from 'react'; +import { HTTPFields, TCPFields, ICMPFields, BrowserFields, ITLSFields, DataStream } from '../types'; +import { + PolicyConfigContextProvider, + TCPContextProvider, + ICMPSimpleFieldsContextProvider, + HTTPContextProvider, + BrowserContextProvider, + TLSFieldsContextProvider, +} from '.'; + +interface Props { + children: React.ReactNode; + httpDefaultValues?: HTTPFields; + tcpDefaultValues?: TCPFields; + icmpDefaultValues?: ICMPFields; + browserDefaultValues?: BrowserFields; + tlsDefaultValues?: ITLSFields; + policyDefaultValues?: { + defaultMonitorType: DataStream; + defaultIsTLSEnabled: boolean; + defaultIsZipUrlTLSEnabled: boolean; + defaultName?: string; + defaultLocations?: string[]; + isEditable: boolean; + }; +} + +export const SyntheticsProviders = ({ + children, + httpDefaultValues, + tcpDefaultValues, + icmpDefaultValues, + browserDefaultValues, + tlsDefaultValues, + policyDefaultValues, +}: Props) => { + return ( + + + + + + + {children} + + + + + + + ); +}; diff --git a/x-pack/plugins/uptime/public/components/fleet_package/custom_fields.tsx b/x-pack/plugins/uptime/public/components/fleet_package/custom_fields.tsx index f8754307e0820..1952d50cdd92a 100644 --- a/x-pack/plugins/uptime/public/components/fleet_package/custom_fields.tsx +++ b/x-pack/plugins/uptime/public/components/fleet_package/custom_fields.tsx @@ -33,6 +33,7 @@ import { BrowserAdvancedFields } from './browser/advanced_fields'; interface Props { validate: Validation; dataStreams?: DataStream[]; + children?: React.ReactNode; } const dataStreamToString = [ @@ -50,7 +51,7 @@ const dataStreamToString = [ }, ]; -export const CustomFields = memo(({ validate, dataStreams = [] }) => { +export const CustomFields = memo(({ validate, dataStreams = [], children }) => { const { monitorType, setMonitorType, isTLSEnabled, setIsTLSEnabled, isEditable } = usePolicyConfigContext(); @@ -98,6 +99,7 @@ export const CustomFields = memo(({ validate, dataStreams = [] }) => { > + {children} {!isEditable && ( { - const { isTLSEnabled, isZipUrlTLSEnabled } = usePolicyConfigContext(); +export const usePolicy = (fleetPolicyName: string = '') => { + const { + isTLSEnabled, + isZipUrlTLSEnabled, + name: monitorName, // the monitor name can come from two different places, either from fleet or from uptime + } = usePolicyConfigContext(); const { fields: httpSimpleFields } = useHTTPSimpleFieldsContext(); const { fields: tcpSimpleFields } = useTCPSimpleFieldsContext(); const { fields: icmpSimpleFields } = useICMPSimpleFieldsContext(); @@ -77,6 +77,7 @@ export const usePolicy = (name: string) => { [isTLSEnabled, isZipUrlTLSEnabled] ); + /* TODO add locations to policy config for synthetics service */ const policyConfig: PolicyConfig = useMemo( () => ({ [DataStream.HTTP]: { @@ -87,7 +88,7 @@ export const usePolicy = (name: string) => { ...httpSimpleFields[ConfigKeys.METADATA], ...metadata, }, - [ConfigKeys.NAME]: name, + [ConfigKeys.NAME]: fleetPolicyName || monitorName, } as HTTPFields, [DataStream.TCP]: { ...tcpSimpleFields, @@ -97,11 +98,11 @@ export const usePolicy = (name: string) => { ...tcpSimpleFields[ConfigKeys.METADATA], ...metadata, }, - [ConfigKeys.NAME]: name, + [ConfigKeys.NAME]: fleetPolicyName || monitorName, } as TCPFields, [DataStream.ICMP]: { ...icmpSimpleFields, - [ConfigKeys.NAME]: name, + [ConfigKeys.NAME]: fleetPolicyName || monitorName, } as ICMPFields, [DataStream.BROWSER]: { ...browserSimpleFields, @@ -110,7 +111,7 @@ export const usePolicy = (name: string) => { ...browserSimpleFields[ConfigKeys.METADATA], ...metadata, }, - [ConfigKeys.NAME]: name, + [ConfigKeys.NAME]: fleetPolicyName || monitorName, } as BrowserFields, }), [ @@ -123,7 +124,8 @@ export const usePolicy = (name: string) => { browserSimpleFields, browserAdvancedFields, tlsFields, - name, + fleetPolicyName, + monitorName, ] ); diff --git a/x-pack/plugins/uptime/public/components/fleet_package/synthetics_policy_create_extension_wrapper.tsx b/x-pack/plugins/uptime/public/components/fleet_package/synthetics_policy_create_extension_wrapper.tsx index c3b2b632850be..e3e13b16ebf22 100644 --- a/x-pack/plugins/uptime/public/components/fleet_package/synthetics_policy_create_extension_wrapper.tsx +++ b/x-pack/plugins/uptime/public/components/fleet_package/synthetics_policy_create_extension_wrapper.tsx @@ -8,14 +8,7 @@ import React, { memo } from 'react'; import { PackagePolicyCreateExtensionComponentProps } from '../../../../fleet/public'; import { SyntheticsPolicyCreateExtension } from './synthetics_policy_create_extension'; -import { - PolicyConfigContextProvider, - TCPContextProvider, - ICMPSimpleFieldsContextProvider, - HTTPContextProvider, - BrowserContextProvider, - TLSFieldsContextProvider, -} from './contexts'; +import { SyntheticsProviders } from './contexts'; /** * Exports Synthetics-specific package policy instructions @@ -24,19 +17,9 @@ import { export const SyntheticsPolicyCreateExtensionWrapper = memo(({ newPolicy, onChange }) => { return ( - - - - - - - - - - - - - + + + ); }); SyntheticsPolicyCreateExtensionWrapper.displayName = 'SyntheticsPolicyCreateExtensionWrapper'; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/formatters/browser.ts b/x-pack/plugins/uptime/public/components/monitor_management/formatters/browser.ts new file mode 100644 index 0000000000000..e4a84e2bb85b5 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/formatters/browser.ts @@ -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 { BrowserFields, ConfigKeys } from '../../fleet_package/types'; +import { Formatter, commonFormatters, objectFormatter, arrayFormatter } from './common'; + +export type BrowserFormatMap = Record; + +export const browserFormatters: BrowserFormatMap = { + [ConfigKeys.METADATA]: (fields) => objectFormatter(fields[ConfigKeys.METADATA]), + [ConfigKeys.SOURCE_ZIP_URL]: null, + [ConfigKeys.SOURCE_ZIP_USERNAME]: null, + [ConfigKeys.SOURCE_ZIP_PASSWORD]: null, + [ConfigKeys.SOURCE_ZIP_FOLDER]: null, + [ConfigKeys.SOURCE_ZIP_PROXY_URL]: null, + [ConfigKeys.SOURCE_INLINE]: null, + [ConfigKeys.PARAMS]: null, + [ConfigKeys.SCREENSHOTS]: null, + [ConfigKeys.SYNTHETICS_ARGS]: (fields) => null, + [ConfigKeys.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES]: null, + [ConfigKeys.ZIP_URL_TLS_CERTIFICATE]: null, + [ConfigKeys.ZIP_URL_TLS_KEY]: null, + [ConfigKeys.ZIP_URL_TLS_KEY_PASSPHRASE]: null, + [ConfigKeys.ZIP_URL_TLS_VERIFICATION_MODE]: null, + [ConfigKeys.ZIP_URL_TLS_VERSION]: (fields) => + arrayFormatter(fields[ConfigKeys.ZIP_URL_TLS_VERSION]), + [ConfigKeys.JOURNEY_FILTERS_MATCH]: null, + [ConfigKeys.JOURNEY_FILTERS_TAGS]: null, + [ConfigKeys.IGNORE_HTTPS_ERRORS]: null, + ...commonFormatters, +}; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/formatters/common.ts b/x-pack/plugins/uptime/public/components/monitor_management/formatters/common.ts new file mode 100644 index 0000000000000..92d2b28f1283d --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/formatters/common.ts @@ -0,0 +1,31 @@ +/* + * 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 { ICommonFields, ICustomFields, ConfigKeys } from '../../fleet_package/types'; + +export type Formatter = + | null + | ((fields: Partial) => string | string[] | Record | null); + +export type CommonFormatMap = Record; + +export const commonFormatters: CommonFormatMap = { + [ConfigKeys.NAME]: null, + [ConfigKeys.MONITOR_TYPE]: null, + [ConfigKeys.SCHEDULE]: (fields) => + `@every ${fields[ConfigKeys.SCHEDULE]?.number}${fields[ConfigKeys.SCHEDULE]?.unit}`, + [ConfigKeys.APM_SERVICE_NAME]: null, + [ConfigKeys.TAGS]: null, + [ConfigKeys.TIMEOUT]: (fields) => secondsToCronFormatter(fields[ConfigKeys.TIMEOUT]), +}; + +export const arrayFormatter = (value: string[] = []) => (value.length ? value : null); + +export const secondsToCronFormatter = (value: string = '') => (value ? `${value}s` : null); + +export const objectFormatter = (value: Record = {}) => + Object.keys(value).length ? value : null; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/formatters/http.ts b/x-pack/plugins/uptime/public/components/monitor_management/formatters/http.ts new file mode 100644 index 0000000000000..41e162cff2d05 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/formatters/http.ts @@ -0,0 +1,37 @@ +/* + * 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 { HTTPFields, ConfigKeys } from '../../fleet_package/types'; +import { Formatter, commonFormatters, objectFormatter, arrayFormatter } from './common'; +import { tlsFormatters } from './tls'; + +export type HTTPFormatMap = Record; + +export const httpFormatters: HTTPFormatMap = { + [ConfigKeys.METADATA]: (fields) => objectFormatter(fields[ConfigKeys.METADATA]), + [ConfigKeys.URLS]: null, + [ConfigKeys.MAX_REDIRECTS]: null, + [ConfigKeys.USERNAME]: null, + [ConfigKeys.PASSWORD]: null, + [ConfigKeys.PROXY_URL]: null, + [ConfigKeys.RESPONSE_BODY_CHECK_NEGATIVE]: (fields) => + arrayFormatter(fields[ConfigKeys.RESPONSE_BODY_CHECK_NEGATIVE]), + [ConfigKeys.RESPONSE_BODY_CHECK_POSITIVE]: (fields) => + arrayFormatter(fields[ConfigKeys.RESPONSE_BODY_CHECK_POSITIVE]), + [ConfigKeys.RESPONSE_BODY_INDEX]: null, + [ConfigKeys.RESPONSE_HEADERS_CHECK]: (fields) => + objectFormatter(fields[ConfigKeys.RESPONSE_HEADERS_CHECK]), + [ConfigKeys.RESPONSE_HEADERS_INDEX]: null, + [ConfigKeys.RESPONSE_STATUS_CHECK]: (fields) => + arrayFormatter(fields[ConfigKeys.RESPONSE_STATUS_CHECK]), + [ConfigKeys.REQUEST_BODY_CHECK]: (fields) => fields[ConfigKeys.REQUEST_BODY_CHECK]?.value || null, + [ConfigKeys.REQUEST_HEADERS_CHECK]: (fields) => + objectFormatter(fields[ConfigKeys.REQUEST_HEADERS_CHECK]), + [ConfigKeys.REQUEST_METHOD_CHECK]: null, + ...tlsFormatters, + ...commonFormatters, +}; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/formatters/icmp.ts b/x-pack/plugins/uptime/public/components/monitor_management/formatters/icmp.ts new file mode 100644 index 0000000000000..841f986309482 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/formatters/icmp.ts @@ -0,0 +1,17 @@ +/* + * 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 { ICMPFields, ConfigKeys } from '../../fleet_package/types'; +import { Formatter, commonFormatters, secondsToCronFormatter } from './common'; + +export type ICMPFormatMap = Record; + +export const icmpFormatters: ICMPFormatMap = { + [ConfigKeys.HOSTS]: null, + [ConfigKeys.WAIT]: (fields) => secondsToCronFormatter(fields[ConfigKeys.WAIT]), + ...commonFormatters, +}; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/formatters/index.ts b/x-pack/plugins/uptime/public/components/monitor_management/formatters/index.ts new file mode 100644 index 0000000000000..56dac35596d45 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/formatters/index.ts @@ -0,0 +1,38 @@ +/* + * 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 { DataStream } from '../../fleet_package/types'; + +import { httpFormatters, HTTPFormatMap } from './http'; +import { tcpFormatters, TCPFormatMap } from './tcp'; +import { icmpFormatters, ICMPFormatMap } from './icmp'; +import { browserFormatters, BrowserFormatMap } from './browser'; +import { commonFormatters, CommonFormatMap } from './common'; + +type Formatters = HTTPFormatMap & TCPFormatMap & ICMPFormatMap & BrowserFormatMap & CommonFormatMap; + +interface FormatterMap { + [DataStream.HTTP]: HTTPFormatMap; + [DataStream.ICMP]: ICMPFormatMap; + [DataStream.TCP]: TCPFormatMap; + [DataStream.BROWSER]: BrowserFormatMap; +} + +export const formattersMap: FormatterMap = { + [DataStream.HTTP]: httpFormatters, + [DataStream.ICMP]: icmpFormatters, + [DataStream.TCP]: tcpFormatters, + [DataStream.BROWSER]: browserFormatters, +}; + +export const formatters: Formatters = { + ...httpFormatters, + ...icmpFormatters, + ...tcpFormatters, + ...browserFormatters, + ...commonFormatters, +}; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/formatters/tcp.ts b/x-pack/plugins/uptime/public/components/monitor_management/formatters/tcp.ts new file mode 100644 index 0000000000000..cdf77307a6938 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/formatters/tcp.ts @@ -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 { TCPFields, ConfigKeys } from '../../fleet_package/types'; +import { Formatter, commonFormatters } from './common'; +import { tlsFormatters } from './tls'; + +export type TCPFormatMap = Record; + +export const tcpFormatters: TCPFormatMap = { + [ConfigKeys.METADATA]: null, + [ConfigKeys.HOSTS]: null, + [ConfigKeys.PROXY_URL]: null, + [ConfigKeys.PROXY_USE_LOCAL_RESOLVER]: null, + [ConfigKeys.RESPONSE_RECEIVE_CHECK]: null, + [ConfigKeys.REQUEST_SEND_CHECK]: null, + ...tlsFormatters, + ...commonFormatters, +}; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/formatters/tls.ts b/x-pack/plugins/uptime/public/components/monitor_management/formatters/tls.ts new file mode 100644 index 0000000000000..5f7ce27637f3e --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/formatters/tls.ts @@ -0,0 +1,20 @@ +/* + * 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 { ITLSFields, ConfigKeys } from '../../fleet_package/types'; +import { arrayFormatter, Formatter } from './common'; + +type TLSFormatMap = Record; + +export const tlsFormatters: TLSFormatMap = { + [ConfigKeys.TLS_CERTIFICATE_AUTHORITIES]: null, + [ConfigKeys.TLS_CERTIFICATE]: null, + [ConfigKeys.TLS_KEY]: null, + [ConfigKeys.TLS_KEY_PASSPHRASE]: null, + [ConfigKeys.TLS_VERIFICATION_MODE]: null, + [ConfigKeys.TLS_VERSION]: (fields) => arrayFormatter(fields[ConfigKeys.TLS_VERSION]), +}; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/hooks/use_format_monitor.ts b/x-pack/plugins/uptime/public/components/monitor_management/hooks/use_format_monitor.ts new file mode 100644 index 0000000000000..9027aa4520418 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/hooks/use_format_monitor.ts @@ -0,0 +1,62 @@ +/* + * 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 { useEffect, useRef, useState } from 'react'; +import { omitBy, isNil } from 'lodash'; +import { ConfigKeys, DataStream, Validation, ICustomFields } from '../../fleet_package/types'; +import { formatters } from '../formatters'; + +interface Props { + monitorType: DataStream; + defaultConfig: Partial; + config: Partial; + validate: Record; +} + +const formatMonitorConfig = (configKeys: ConfigKeys[], config: Partial) => { + const formattedMonitor = {} as Record; + + configKeys.forEach((key) => { + const value = config[key] ?? null; + if (value && formatters[key]) { + formattedMonitor[key] = formatters[key]?.(config); + } else if (value) { + formattedMonitor[key] = value; + } + }); + + return omitBy(formattedMonitor, isNil) as Partial; +}; + +export const useFormatMonitor = ({ monitorType, defaultConfig, config, validate }: Props) => { + const [formattedMonitor, setFormattedMonitor] = useState>( + formatMonitorConfig(Object.keys(config) as ConfigKeys[], config) + ); + const [isValid, setIsValid] = useState(false); + const currentConfig = useRef>(defaultConfig); + + useEffect(() => { + const configKeys = Object.keys(config) as ConfigKeys[]; + const validationKeys = Object.keys(validate[monitorType]) as ConfigKeys[]; + const configDidUpdate = configKeys.some((key) => config[key] !== currentConfig.current[key]); + const isValidT = + !!config.name && !validationKeys.find((key) => validate[monitorType]?.[key]?.(config)); + + // prevent an infinite loop of updating the policy + if (configDidUpdate) { + const formattedMonitorT = formatMonitorConfig(configKeys, config); + currentConfig.current = config; + setFormattedMonitor(formattedMonitorT); + setIsValid(isValidT); + } + }, [config, currentConfig, validate, monitorType]); + + return { + config, + isValid, + formattedMonitor, + }; +}; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_config.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_config.tsx new file mode 100644 index 0000000000000..081ceee1fe63c --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_config.tsx @@ -0,0 +1,37 @@ +/* + * 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 React from 'react'; + +import { defaultConfig, usePolicyConfigContext } from '../fleet_package/contexts'; + +import { usePolicy } from '../fleet_package/hooks/use_policy'; +import { validate } from '../fleet_package/validation'; +import { MonitorFields } from './monitor_fields'; +import { useFormatMonitor } from './hooks/use_format_monitor'; + +export const MonitorConfig = () => { + const { monitorType } = usePolicyConfigContext(); + /* TODO - Use Effect to make sure the package/index templates are loaded. Wait for it to load before showing view + * then show error message if it fails */ + + /* raw policy config compatible with the UI. Save this to saved objects */ + const policyConfig = usePolicy(); + + /* Policy config that heartbeat can read. Send this to the service. + This type of helper should ideally be moved to task manager where we are syncing the config. + We can process validation (isValid) and formatting for heartbeat (formattedMonitor) separately + We don't need to save the heartbeat compatible version in saved objects */ + useFormatMonitor({ + monitorType, + validate, + config: policyConfig[monitorType], + defaultConfig: defaultConfig[monitorType], + }); + + return ; +}; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_fields.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_fields.tsx new file mode 100644 index 0000000000000..30659e6c2cf40 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_fields.tsx @@ -0,0 +1,29 @@ +/* + * 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 React from 'react'; +import { EuiForm } from '@elastic/eui'; +import { DataStream } from '../fleet_package/types'; +import { usePolicyConfigContext } from '../fleet_package/contexts'; + +import { CustomFields } from '../fleet_package/custom_fields'; +import { validate } from '../fleet_package/validation'; +import { MonitorNameAndLocation } from './monitor_name_location'; + +export const MonitorFields = () => { + const { monitorType } = usePolicyConfigContext(); + return ( + + + + + + ); +}; diff --git a/x-pack/plugins/uptime/public/components/monitor_management/monitor_name_location.tsx b/x-pack/plugins/uptime/public/components/monitor_management/monitor_name_location.tsx new file mode 100644 index 0000000000000..6ee3eacd81cd8 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor_management/monitor_name_location.tsx @@ -0,0 +1,37 @@ +/* + * 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 React from 'react'; +import { EuiFormRow, EuiFieldText } from '@elastic/eui'; +import { usePolicyConfigContext } from '../fleet_package/contexts'; + +export const MonitorNameAndLocation = () => { + const { name, setName } = usePolicyConfigContext(); + return ( + <> + + setName(event.target.value)} + /> + + {/* TODO: connect locations */} + {/* + setLocations(selOptions.map(({ value }) => value as string))} + /> + */} + + ); +}; diff --git a/x-pack/plugins/uptime/public/pages/add_monitor.tsx b/x-pack/plugins/uptime/public/pages/add_monitor.tsx index 10e3d9d6ce29a..a5f925e4712af 100644 --- a/x-pack/plugins/uptime/public/pages/add_monitor.tsx +++ b/x-pack/plugins/uptime/public/pages/add_monitor.tsx @@ -6,7 +6,17 @@ */ import React from 'react'; +import { useTrackPageview } from '../../../observability/public'; +import { SyntheticsProviders } from '../components/fleet_package/contexts'; +import { MonitorConfig } from '../components/monitor_management/monitor_config'; export const AddMonitorPage: React.FC = () => { - return null; + useTrackPageview({ app: 'uptime', path: 'add-monitor' }); + useTrackPageview({ app: 'uptime', path: 'add-monitor', delay: 15000 }); + + return ( + + + + ); }; diff --git a/x-pack/plugins/uptime/public/pages/edit_monitor.tsx b/x-pack/plugins/uptime/public/pages/edit_monitor.tsx index 3be1bc7b35d8d..965639bd12145 100644 --- a/x-pack/plugins/uptime/public/pages/edit_monitor.tsx +++ b/x-pack/plugins/uptime/public/pages/edit_monitor.tsx @@ -5,8 +5,101 @@ * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; +import { + ConfigKeys, + ICustomFields, + ITLSFields, + PolicyConfig, + DataStream, +} from '../components/fleet_package/types'; +import { useTrackPageview } from '../../../observability/public'; +import { SyntheticsProviders } from '../components/fleet_package/contexts'; +import { MonitorConfig } from '../components/monitor_management/monitor_config'; export const EditMonitorPage: React.FC = () => { - return null; + useTrackPageview({ app: 'uptime', path: 'edit-monitor' }); + useTrackPageview({ app: 'uptime', path: 'edit-monitor', delay: 15000 }); + + const { + enableTLS: isTLSEnabled, + enableZipUrlTLS: isZipUrlTLSEnabled, + fullConfig: fullDefaultConfig, + monitorTypeConfig: defaultConfig, + monitorType, + tlsConfig: defaultTLSConfig, + } = useMemo(() => { + /* TODO: fetch current monitor to be edited from saved objects based on url param */ + const monitor = {} as Record; // fetch + + let enableTLS = false; + let enableZipUrlTLS = false; + const getDefaultConfig = () => { + const type: DataStream = monitor[ConfigKeys.MONITOR_TYPE] as DataStream; + + const configKeys: ConfigKeys[] = Object.values(ConfigKeys) || ([] as ConfigKeys[]); + const formattedDefaultConfigForMonitorType: ICustomFields = configKeys.reduce( + (acc: ICustomFields, key: ConfigKeys) => { + return { + ...acc, + key, + }; + }, + {} as ICustomFields + ); + + const tlsConfig: ITLSFields = { + [ConfigKeys.TLS_CERTIFICATE_AUTHORITIES]: + formattedDefaultConfigForMonitorType[ConfigKeys.TLS_CERTIFICATE_AUTHORITIES], + [ConfigKeys.TLS_CERTIFICATE]: + formattedDefaultConfigForMonitorType[ConfigKeys.TLS_CERTIFICATE], + [ConfigKeys.TLS_KEY]: formattedDefaultConfigForMonitorType[ConfigKeys.TLS_KEY], + [ConfigKeys.TLS_KEY_PASSPHRASE]: + formattedDefaultConfigForMonitorType[ConfigKeys.TLS_KEY_PASSPHRASE], + [ConfigKeys.TLS_VERIFICATION_MODE]: + formattedDefaultConfigForMonitorType[ConfigKeys.TLS_VERIFICATION_MODE], + [ConfigKeys.TLS_VERSION]: formattedDefaultConfigForMonitorType[ConfigKeys.TLS_VERSION], + }; + + enableTLS = Boolean(formattedDefaultConfigForMonitorType[ConfigKeys.TLS_VERIFICATION_MODE]); + enableZipUrlTLS = Boolean( + formattedDefaultConfigForMonitorType[ConfigKeys.ZIP_URL_TLS_VERIFICATION_MODE] + ); + + const formattedDefaultConfig: Partial = { + [type]: formattedDefaultConfigForMonitorType, + }; + + return { + fullConfig: formattedDefaultConfig, + monitorTypeConfig: formattedDefaultConfigForMonitorType, + tlsConfig, + monitorType: type, + enableTLS, + enableZipUrlTLS, + }; + }; + + return getDefaultConfig(); + }, []); + + return ( + + + + ); };